0030807: Visualization, TKOpenGl - supporting cubemaps
[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 variable set of options that are allowed for the old scenario (without any option passed)
420     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
421
422     //! the variable set of options that are allowed for setting an environment cubemap as background
423     CommandOptionKeyVariableSet myCubeMapOptionVariableSet;
424
425     //! the variable set of options that are allowed for setting an image as a background
426     CommandOptionKeyVariableSet myImageOptionVariableSet;
427
428     //! the variable set of options that are allowed for setting a background image fill type
429     CommandOptionKeyVariableSet myImageModeOptionVariableSet;
430
431     //! the variable set of options that are allowed for setting a gradient filling for the background
432     CommandOptionKeyVariableSet myGradientOptionVariableSet;
433
434     //! the variable set of options that are allowed for setting a background gradient filling method
435     CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
436
437     //! the variable set of options that are allowed for filling a background with a specific color
438     CommandOptionKeyVariableSet myColorOptionVariableSet;
439
440     //! the variable set of options that are allowed for setting a default background gradient
441     CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
442
443     //! the variable set of options that are allowed for setting a default background color
444     CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
445
446     //! the variable set of options that are allowed for printing help
447     CommandOptionKeyVariableSet myHelpOptionVariableSet;
448
449     //! Adds options to command parser
450     void addOptionsToCommandParser()
451     {
452       myImageOptionKey     = myCommandParser.AddOption ("imageFile|image|imgFile|img",
453                                                     "filename of image used as background");
454       myImageModeOptionKey = myCommandParser.AddOption (
455         "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
456       myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
457                                                        "sets background gradient starting and ending colors");
458       myGradientModeOptionKey =
459         myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
460                                    "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
461                                    "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
462       myColorOptionKey   = myCommandParser.AddOption ("color|col", "background color");
463       myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
464
465       myCubeMapOptionKey           = myCommandParser.AddOption ("cubemap|cmap|cm", "background cubemap");
466       myCubeMapOrderOptionKey      = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
467       myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
468         "invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
469     }
470
471     //! Creates option sets used to determine if a passed option set is valid or not
472     void createOptionSets()
473     {
474       ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
475       anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
476       myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
477
478       ViewerTest_CommandOptionKeySet aCubeMapOptionSet;
479       aCubeMapOptionSet.insert (myCubeMapOptionKey);
480       ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
481       aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
482       aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
483       myCubeMapOptionVariableSet     = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
484
485       ViewerTest_CommandOptionKeySet anImageOptionSet;
486       anImageOptionSet.insert (myImageOptionKey);
487       ViewerTest_CommandOptionKeySet anImageModeOptionSet;
488       anImageModeOptionSet.insert (myImageModeOptionKey);
489       myImageOptionVariableSet     = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
490       myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
491
492       ViewerTest_CommandOptionKeySet aGradientOptionSet;
493       aGradientOptionSet.insert (myGradientOptionKey);
494       ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
495       aGradientModeOptionSet.insert (myGradientModeOptionKey);
496       myGradientOptionVariableSet     = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
497       myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
498
499       ViewerTest_CommandOptionKeySet aColorOptionSet;
500       aColorOptionSet.insert (myColorOptionKey);
501       myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
502
503       aGradientOptionSet.insert (myDefaultOptionKey);
504       myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
505       aColorOptionSet.insert (myDefaultOptionKey);
506       myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
507
508       ViewerTest_CommandOptionKeySet aHelpOptionSet;
509       aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
510       myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
511     }
512
513     //! Prepares the command parser. Adds options and creates option sets used to determine
514     //! if a passed option set is valid or not
515     void prepareCommandParser()
516     {
517       addOptionsToCommandParser();
518       createOptionSets();
519     }
520
521     //! Adds a command description to the command parser
522     //! @param theBackgroundCommand the key of the command which description is added to the command parser
523     void addCommandDescription (const BackgroundCommand theBackgroundCommand)
524     {
525       std::string aDescription;
526       bool        isMainCommand = false;
527       switch (theBackgroundCommand)
528       {
529         case BackgroundCommand_Main:
530           aDescription  = "Command: vbackground (changes background or some background settings)";
531           isMainCommand = true;
532           break;
533         case BackgroundCommand_Image:
534           aDescription = "Command: vsetbg (loads image as a background)";
535           break;
536         case BackgroundCommand_ImageMode:
537           aDescription = "Command: vsetbgmode (changes background fill type)";
538           break;
539         case BackgroundCommand_Gradient:
540           aDescription = "Command: vsetgradientbg (mounts gradient background)";
541           break;
542         case BackgroundCommand_GradientMode:
543           aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
544           break;
545         case BackgroundCommand_Color:
546           aDescription = "Command: vsetcolorbg (sets color background)";
547           break;
548         case BackgroundCommand_Default:
549           aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
550           break;
551         default:
552           return;
553       }
554       if (!isMainCommand)
555       {
556         aDescription += "\nThis command is obsolete. Use vbackground instead.";
557       }
558       myCommandParser.SetDescription (aDescription);
559     }
560
561     //! Check if a viewer is needed to be initialized
562     //! @param theBackgroundCommand the key of the command that changes the background
563     //! @return true if processing was successful, or false otherwise
564     bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
565     {
566       const bool                           isMain             = (theBackgroundCommand == BackgroundCommand_Main);
567       const ViewerTest_CommandOptionKeySet aUsedOptions       = myCommandParser.GetUsedOptions();
568       const bool                           aViewerIsNotNeeded =
569         (theBackgroundCommand == BackgroundCommand_Default)
570         || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
571         || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
572         || myHelpOptionVariableSet.IsInSet (aUsedOptions);
573       return !aViewerIsNotNeeded;
574     }
575
576     //! Check if a viewer is initialized
577     //! @param theBackgroundCommandName the name of the command that changes the background
578     //! @param theDrawInterpretor the interpreter of the Draw Harness application
579     //! @return true if a viewer is initialized, or false otherwise
580     static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
581                                           Draw_Interpretor& theDrawInterpretor)
582     {
583       const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
584       if (anAISContext.IsNull())
585       {
586         theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
587         return false;
588       }
589       return true;
590     }
591
592     //! Processes command options
593     //! @param theBackgroundCommandName the name of the command that changes the background
594     //! @param theBackgroundCommand the key of the command that changes the background
595     //! @param theDrawInterpretor the interpreter of the Draw Harness application
596     //! @return true if processing was successful, or false otherwise
597     bool processCommandOptions (const char* const       theBackgroundCommandName,
598                                 const BackgroundCommand theBackgroundCommand,
599                                 Draw_Interpretor&       theDrawInterpretor) const
600     {
601       if (myCommandParser.HasNoOption())
602       {
603         return printHelp (theBackgroundCommandName, theDrawInterpretor);
604       }
605       if (checkViewerIsNeeded (theBackgroundCommand)
606           && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
607       {
608         return false;
609       }
610       if (myCommandParser.HasOnlyUnnamedOption())
611       {
612         return processUnnamedOption (theBackgroundCommand);
613       }
614       return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
615     }
616
617     //! Processes the unnamed option
618     //! @param theBackgroundCommand the key of the command that changes the background
619     //! @return true if processing was successful, or false otherwise
620     bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
621     {
622       switch (theBackgroundCommand)
623       {
624         case BackgroundCommand_Main:
625           return false;
626         case BackgroundCommand_Image:
627           return processImageUnnamedOption();
628         case BackgroundCommand_ImageMode:
629           return processImageModeUnnamedOption();
630         case BackgroundCommand_Gradient:
631           return processGradientUnnamedOption();
632         case BackgroundCommand_GradientMode:
633           return processGradientModeUnnamedOption();
634         case BackgroundCommand_Color:
635           return processColorUnnamedOption();
636         case BackgroundCommand_Default:
637           return processDefaultUnnamedOption();
638         default:
639           return false;
640       }
641     }
642
643     //! Processes the image unnamed option
644     //! @return true if processing was successful, or false otherwise
645     bool processImageUnnamedOption() const
646     {
647       const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
648         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
649       if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
650       {
651         return false;
652       }
653       std::string anImageFileName;
654       if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
655       {
656         return false;
657       }
658       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
659       if (aNumberOfImageUnnamedOptionArguments == 2)
660       {
661         std::string anImageModeString;
662         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
663         {
664           return false;
665         }
666         if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
667         {
668           return false;
669         }
670       }
671       setImage (anImageFileName.c_str(), anImageMode);
672       return true;
673     }
674
675     //! Processes the image mode unnamed option
676     //! @return true if processing was successful, or false otherwise
677     bool processImageModeUnnamedOption() const
678     {
679       return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
680     }
681
682     //! Processes the gradient unnamed option
683     //! @param theSetGradient the function used to set a background gradient filling
684     //! @return true if processing was successful, or false otherwise
685     bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
686     {
687       const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
688         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
689       if (aNumberOfGradientUnnamedOptionArguments < 2)
690       {
691         return false;
692       }
693
694       Standard_Integer anArgumentIndex = 0;
695       Quantity_Color   aColor1;
696       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
697       {
698         return false;
699       }
700       if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
701       {
702         return false;
703       }
704
705       Quantity_Color aColor2;
706       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
707       {
708         return false;
709       }
710       if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
711       {
712         return false;
713       }
714
715       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
716       if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
717       {
718         std::string anGradientModeString;
719
720         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
721                                   anArgumentIndex,
722                                   anGradientModeString))
723         {
724           return false;
725         }
726         if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
727         {
728           return false;
729         }
730         ++anArgumentIndex;
731       }
732       if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
733       {
734         return false;
735       }
736       theSetGradient (aColor1, aColor2, aGradientMode);
737       return true;
738     }
739
740     //! Processes the gradient mode unnamed option
741     //! @return true if processing was successful, or false otherwise
742     bool processGradientModeUnnamedOption() const
743     {
744       return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
745     }
746
747     //! Processes the color unnamed option
748     //! @param theSetColor the function used to set a background color
749     //! @return true if processing was successful, or false otherwise
750     bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
751     {
752       return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
753     }
754
755     //! Processes the default back unnamed option
756     //! @return true if processing was successful, or false otherwise
757     bool processDefaultUnnamedOption() const
758     {
759       if (processGradientUnnamedOption (setDefaultGradient))
760       {
761         return true;
762       }
763       return processColorUnnamedOption (setDefaultColor);
764     }
765
766     //! Processes named options
767     //! @param theBackgroundCommandName the name of the command that changes the background
768     //! @param theBackgroundCommand the key of the command that changes the background
769     //! @param theDrawInterpretor the interpreter of the Draw Harness application
770     //! @return true if processing was successful, or false otherwise
771     bool processNamedOptions (const char* const       theBackgroundCommandName,
772                               const BackgroundCommand theBackgroundCommand,
773                               Draw_Interpretor&       theDrawInterpretor) const
774     {
775       const bool                           isMain       = (theBackgroundCommand == BackgroundCommand_Main);
776       const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
777       if (myCubeMapOptionVariableSet.IsInSet (aUsedOptions) && isMain)
778       {
779         return processCubeMapOptionSet();
780       }
781       if (myImageOptionVariableSet.IsInSet (aUsedOptions)
782           && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
783       {
784         return processImageOptionSet();
785       }
786       if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
787           && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
788       {
789         return processImageModeOptionSet();
790       }
791       if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
792           && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
793       {
794         return processGradientOptionSet();
795       }
796       if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
797           && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
798       {
799         return processGradientModeOptionSet();
800       }
801       if (myColorOptionVariableSet.IsInSet (aUsedOptions)
802           && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
803       {
804         return processColorOptionSet();
805       }
806       if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
807           || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
808               && (theBackgroundCommand == BackgroundCommand_Default)))
809       {
810         return processDefaultGradientOptionSet();
811       }
812       if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
813           || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
814       {
815         return processDefaultColorOptionSet();
816       }
817       if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
818       {
819         return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
820       }
821       return false;
822     }
823
824     //! Process the cubemap option set in named and unnamed case.
825     //! @return true if processing was successful, or false otherwise
826     bool processCubeMapOptionSet() const
827     {
828       NCollection_Array1<TCollection_AsciiString> aFilePaths;
829
830       if (!processCubeMapOptions (aFilePaths))
831       {
832         return false;
833       }
834
835       Graphic3d_CubeMapOrder anOrder = Graphic3d_CubeMapOrder::Default();
836
837       if (myCommandParser.HasOption (myCubeMapOrderOptionKey))
838       {
839         if (!processCubeMapOrderOptions (anOrder))
840         {
841           return false;
842         }
843       }
844
845       bool aZIsInverted = false;
846       if (myCommandParser.HasOption (myCubeMapInvertedZOptionKey))
847       {
848         if (!processCubeMapInvertedZOptionSet())
849         {
850           return false;
851         }
852         aZIsInverted = true;
853       }
854
855       setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted);
856       return true;
857     }
858
859     //! Processes the image option set
860     //! @return true if processing was successful, or false otherwise
861     bool processImageOptionSet() const
862     {
863       std::string anImageFileName;
864       if (!processImageOption (anImageFileName))
865       {
866         return false;
867       }
868       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
869       if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
870       {
871         return false;
872       }
873       setImage (anImageFileName.c_str(), anImageMode);
874       return true;
875     }
876
877     //! Processes the image mode option set
878     //! @return true if processing was successful, or false otherwise
879     bool processImageModeOptionSet() const
880     {
881       return processImageModeOptionSet (myImageModeOptionKey);
882     }
883
884     //! Processes the image mode option set
885     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
886     //! @return true if processing was successful, or false otherwise
887     bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
888     {
889       Aspect_FillMethod anImageMode = Aspect_FM_NONE;
890       if (!processImageModeOption (theImageModeOptionKey, anImageMode))
891       {
892         return false;
893       }
894       setImageMode (anImageMode);
895       return true;
896     }
897
898     //! Processes the gradient option set
899     //! @param theSetGradient the function used to set a background gradient filling
900     //! @return true if processing was successful, or false otherwise
901     bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
902     {
903       Quantity_Color aColor1;
904       Quantity_Color aColor2;
905       if (!processGradientOption (aColor1, aColor2))
906       {
907         return false;
908       }
909       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
910       if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
911       {
912         return false;
913       }
914       theSetGradient (aColor1, aColor2, aGradientMode);
915       return true;
916     }
917
918     //! Processes the gradient mode option set
919     //! @return true if processing was successful, or false otherwise
920     bool processGradientModeOptionSet() const
921     {
922       return processGradientModeOptionSet (myGradientModeOptionKey);
923     }
924
925     //! Processes the gradient mode option set
926     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
927     //! @return true if processing was successful, or false otherwise
928     bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
929     {
930       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
931       if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
932       {
933         return false;
934       }
935       setGradientMode (aGradientMode);
936       return true;
937     }
938
939     //! Processes the color option set
940     //! @param theSetColor the function used to set a background color
941     //! @return true if processing was successful, or false otherwise
942     bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
943     {
944       return processColorOptionSet (myColorOptionKey, theSetColor);
945     }
946
947     //! Processes the default color option set
948     //! @return true if processing was successful, or false otherwise
949     bool processDefaultGradientOptionSet() const
950     {
951       return processGradientOptionSet (setDefaultGradient);
952     }
953
954     //! Processes the default gradient option set
955     //! @return true if processing was successful, or false otherwise
956     bool processDefaultColorOptionSet() const
957     {
958       return processColorOptionSet (setDefaultColor);
959     }
960
961     //! Processes the color option set
962     //! @param theColorOptionKey the key of the option that is interpreted as a color option
963     //! @param theSetColor the function used to set a background color
964     //! @return true if processing was successful, or false otherwise
965     bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
966                                 SetColorFunction* const           theSetColor = setColor) const
967     {
968       Quantity_Color aColor;
969       if (!processColorOption (theColorOptionKey, aColor))
970       {
971         return false;
972       }
973       theSetColor (aColor);
974       return true;
975     }
976
977     //! Processes the help option set
978     //! @param theBackgroundCommandName the name of the command that changes the background
979     //! @param theDrawInterpretor the interpreter of the Draw Harness application
980     //! @return true if processing was successful, or false otherwise
981     bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
982     {
983       const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
984         ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
985       if (aNumberOfHelpOptionArguments != 0)
986       {
987         return false;
988       }
989       return printHelp (theBackgroundCommandName, theDrawInterpretor);
990     }
991
992     //! Processes the cubemap option
993     //! @param theFilePaths the array of filenames of cubemap sides
994     //! @return true if processing was successful, or false otherwise
995     bool processCubeMapOptions (NCollection_Array1<TCollection_AsciiString> &theFilePaths) const
996     {
997       const Standard_Integer aNumberOfCubeMapOptionArguments = myCommandParser.GetNumberOfOptionArguments (myCubeMapOptionKey);
998
999       if (aNumberOfCubeMapOptionArguments != 1
1000        && aNumberOfCubeMapOptionArguments != 6)
1001       {
1002         return false;
1003       }
1004
1005       theFilePaths.Resize(0, aNumberOfCubeMapOptionArguments - 1, Standard_False);
1006
1007       for (int i = 0; i < aNumberOfCubeMapOptionArguments; ++i)
1008       {
1009         std::string aCubeMapFileName;
1010         if (!myCommandParser.Arg (myCubeMapOptionKey, i, aCubeMapFileName))
1011         {
1012           return false;
1013         }
1014         theFilePaths[i] = aCubeMapFileName.c_str();
1015       }
1016
1017       return true;
1018     }
1019
1020     //! Processes the cubemap option
1021     //! @param theIsNeededToRedraw defines need of redraw after option's processing 
1022     //! @return true if processing was successful, or false otherwise
1023     bool processCubeMapInvertedZOptionSet () const
1024     {
1025       const Standard_Integer aNumberOfCubeMapZInversionOptionArguments =
1026         myCommandParser.GetNumberOfOptionArguments (myCubeMapInvertedZOptionKey);
1027
1028       if (aNumberOfCubeMapZInversionOptionArguments != 0)
1029       {
1030         return false;
1031       }
1032
1033       return true;
1034     }
1035
1036     //! Processes the tiles order option
1037     //! @param theOrder the array of indexes if cubemap sides in tile grid
1038     //! @return true if processing was successful, or false otherwise
1039     bool processCubeMapOrderOptions (Graphic3d_CubeMapOrder& theOrder) const
1040     {
1041       const Standard_Integer aNumberOfCubeMapOrderOptionArguments = myCommandParser.GetNumberOfOptionArguments(
1042         myCubeMapOrderOptionKey);
1043
1044       if (aNumberOfCubeMapOrderOptionArguments != 6)
1045       {
1046         return false;
1047       }
1048
1049
1050       for (unsigned int i = 0; i < 6; ++i)
1051       {
1052         std::string anOrderItem;
1053         if (!myCommandParser.Arg (myCubeMapOrderOptionKey, i, anOrderItem)) 
1054         {
1055           return false;
1056         }
1057
1058         theOrder.Set (Graphic3d_CubeMapSide (i),
1059                       static_cast<unsigned char> (Draw::Atoi (anOrderItem.c_str())));
1060       }
1061
1062       return theOrder.IsValid();
1063     }
1064
1065     //! Processes the image option
1066     //! @param theImageFileName the filename of the image to be used as a background
1067     //! @return true if processing was successful, or false otherwise
1068     bool processImageOption (std::string& theImageFileName) const
1069     {
1070       const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1071         myImageOptionKey);
1072       if (aNumberOfImageOptionArguments != 1)
1073       {
1074         return false;
1075       }
1076       std::string anImageFileName;
1077       if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1078       {
1079         return false;
1080       }
1081       theImageFileName = anImageFileName;
1082       return true;
1083     }
1084
1085     //! Processes the image mode option
1086     //! @param theImageMode the fill type used for a background image
1087     //! @return true if processing was successful, or false otherwise
1088     bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1089     {
1090       return processImageModeOption (myImageModeOptionKey, theImageMode);
1091     }
1092
1093     //! Processes the image mode option
1094     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1095     //! @param theImageMode the fill type used for a background image
1096     //! @return true if processing was successful, or false otherwise
1097     bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1098                                  Aspect_FillMethod&                theImageMode) const
1099     {
1100       return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1101     }
1102
1103     //! Processes the gradient option
1104     //! @param theColor1 the gradient starting color
1105     //! @param theColor2 the gradient ending color
1106     //! @return true if processing was successful, or false otherwise
1107     bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1108     {
1109       Standard_Integer anArgumentIndex = 0;
1110       Quantity_Color   aColor1;
1111       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1112       {
1113         return false;
1114       }
1115       Quantity_Color aColor2;
1116       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1117       {
1118         return false;
1119       }
1120       const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1121         myGradientOptionKey);
1122       if (anArgumentIndex != aNumberOfGradientOptionArguments)
1123       {
1124         return false;
1125       }
1126       theColor1 = aColor1;
1127       theColor2 = aColor2;
1128       return true;
1129     }
1130
1131     //! Processes the gradient mode option
1132     //! @param theGradientMode the fill method used for a background gradient filling
1133     //! @return true if processing was successful, or false otherwise
1134     bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1135     {
1136       return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1137     }
1138
1139     //! Processes the gradient mode option
1140     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1141     //! @param theGradientMode the fill method used for a background gradient filling
1142     //! @return true if processing was successful, or false otherwise
1143     bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1144                                     Aspect_GradientFillMethod&        theGradientMode) const
1145     {
1146       return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1147     }
1148
1149     //! Processes some mode option
1150     //! @tparam TheMode the type of a mode to be processed
1151     //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1152     //! @param theMode a mode to be processed
1153     //! @return true if processing was successful, or false otherwise
1154     template <typename TheMode>
1155     bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1156                             bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1157                                                             TheMode& /* theMode */),
1158                             TheMode& theMode) const
1159     {
1160       const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1161         theModeOptionKey);
1162       if (aNumberOfModeOptionArguments != 1)
1163       {
1164         return false;
1165       }
1166       std::string aModeString;
1167       if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1168       {
1169         return false;
1170       }
1171       TheMode aMode = TheMode();
1172       if (!theGetModeByName (aModeString.c_str(), aMode))
1173       {
1174         return false;
1175       }
1176       theMode = aMode;
1177       return true;
1178     }
1179
1180     //! Processes the color option
1181     //! @param theColor a color used for filling a background
1182     //! @return true if processing was successful, or false otherwise
1183     bool processColorOption (Quantity_Color& theColor) const
1184     {
1185       return processColorOption (myColorOptionKey, theColor);
1186     }
1187
1188     //! Processes the color option
1189     //! @param theColorOptionKey the key of the option that is interpreted as a color option
1190     //! @param theColor a color used for filling a background
1191     //! @return true if processing was successful, or false otherwise
1192     bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1193     {
1194       Standard_Integer anArgumentIndex = 0;
1195       Quantity_Color   aColor;
1196       if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1197       {
1198         return false;
1199       }
1200       const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1201         theColorOptionKey);
1202       if (anArgumentIndex != aNumberOfColorOptionArguments)
1203       {
1204         return false;
1205       }
1206       theColor = aColor;
1207       return true;
1208     }
1209
1210     //! Prints helping message
1211     //! @param theBackgroundCommandName the name of the command that changes the background
1212     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1213     //! @return true if printing was successful, or false otherwise
1214     static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1215     {
1216       return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1217     }
1218
1219     //! Sets the cubemap as a background
1220     //! @param theFileNames the array of filenames of packed or multifile cubemap
1221     //! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
1222     static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
1223                             const Graphic3d_ValidatedCubeMapOrder              theOrder = Graphic3d_CubeMapOrder::Default(),
1224                             bool                                               theZIsInverted = false)
1225     {
1226       const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
1227       Handle(Graphic3d_CubeMap) aCubeMap;
1228
1229       if (theFileNames.Size() == 1)
1230         aCubeMap = new Graphic3d_CubeMapPacked(theFileNames[0], theOrder);
1231       else
1232         aCubeMap = new Graphic3d_CubeMapSeparate(theFileNames);
1233
1234       aCubeMap->SetZInversion (theZIsInverted);
1235
1236       aCubeMap->GetParams()->SetFilter(Graphic3d_TOTF_BILINEAR);
1237       aCubeMap->GetParams()->SetRepeat(Standard_False);
1238       aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
1239
1240       aCurrentView->SetBackgroundCubeMap (aCubeMap, Standard_True);
1241     }
1242
1243     //! Sets the image as a background
1244     //! @param theImageFileName the filename of the image to be used as a background
1245     //! @param theImageMode the fill type used for a background image
1246     static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1247     {
1248       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1249       aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1250     }
1251
1252     //! Sets the fill type used for a background image
1253     //! @param theImageMode the fill type used for a background image
1254     static void setImageMode (const Aspect_FillMethod theImageMode)
1255     {
1256       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1257       aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1258     }
1259
1260     //! Sets the gradient filling for a background
1261     //! @param theColor1 the gradient starting color
1262     //! @param theColor2 the gradient ending color
1263     //! @param theGradientMode the fill method used for a background gradient filling
1264     static void setGradient (const Quantity_Color&           theColor1,
1265                              const Quantity_Color&           theColor2,
1266                              const Aspect_GradientFillMethod theGradientMode)
1267     {
1268       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1269       aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1270     }
1271
1272     //! Sets the fill method used for a background gradient filling
1273     //! @param theGradientMode the fill method used for a background gradient filling
1274     static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1275     {
1276       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1277       aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1278     }
1279
1280     //! Sets the color used for filling a background
1281     //! @param theColor the color used for filling a background
1282     static void setColor (const Quantity_Color& theColor)
1283     {
1284       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1285       aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1286       aCurrentView->SetBackgroundColor (theColor);
1287       aCurrentView->Update();
1288     }
1289
1290     //! Sets the gradient filling for a background in a default viewer
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 setDefaultGradient (const Quantity_Color&           theColor1,
1295                                     const Quantity_Color&           theColor2,
1296                                     const Aspect_GradientFillMethod theGradientMode)
1297     {
1298       ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1299       ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1300       ViewerTest_DefaultBackground.FillMethod     = theGradientMode;
1301       setDefaultGradient();
1302     }
1303
1304     //! Sets the color used for filling a background in a default viewer
1305     //! @param theColor the color used for filling a background
1306     static void setDefaultColor (const Quantity_Color& theColor)
1307     {
1308       ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1309       ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1310       ViewerTest_DefaultBackground.FillMethod     = Aspect_GFM_NONE;
1311       ViewerTest_DefaultBackground.FlatColor      = theColor;
1312       setDefaultGradient();
1313       setDefaultColor();
1314     }
1315
1316     //! Sets the gradient filling for a background in a default viewer.
1317     //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1318     static void setDefaultGradient()
1319     {
1320       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1321              anInteractiveContextIterator (ViewerTest_myContexts);
1322            anInteractiveContextIterator.More();
1323            anInteractiveContextIterator.Next())
1324       {
1325         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1326         aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1327                                              ViewerTest_DefaultBackground.GradientColor2,
1328                                              ViewerTest_DefaultBackground.FillMethod);
1329       }
1330     }
1331
1332     //! Sets the color used for filling a background in a default viewer.
1333     //! The color value is taken from ViewerTest_DefaultBackground structure
1334     static void setDefaultColor()
1335     {
1336       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1337              anInteractiveContextIterator (ViewerTest_myContexts);
1338            anInteractiveContextIterator.More();
1339            anInteractiveContextIterator.Next())
1340       {
1341         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1342         aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1343       }
1344     }
1345   };
1346
1347 } // namespace
1348
1349 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
1350
1351 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
1352 {
1353   static ViewerTest_MapOfAISManipulators aMap;
1354   return aMap;
1355 }
1356
1357 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
1358 {
1359   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
1360   for (; anIt.More(); anIt.Next())
1361   {
1362     if (anIt.Value()->HasActiveMode())
1363     {
1364       return anIt.Value();
1365     }
1366   }
1367   return NULL;
1368 }
1369
1370 //==============================================================================
1371
1372 #ifdef _WIN32
1373 static LRESULT WINAPI ViewerWindowProc(
1374                                        HWND hwnd,
1375                                        UINT uMsg,
1376                                        WPARAM wParam,
1377                                        LPARAM lParam );
1378 static LRESULT WINAPI AdvViewerWindowProc(
1379   HWND hwnd,
1380   UINT uMsg,
1381   WPARAM wParam,
1382   LPARAM lParam );
1383 #endif
1384
1385
1386 //==============================================================================
1387 //function : WClass
1388 //purpose  :
1389 //==============================================================================
1390
1391 const Handle(Standard_Transient)& ViewerTest::WClass()
1392 {
1393   static Handle(Standard_Transient) theWClass;
1394 #if defined(_WIN32)
1395   if (theWClass.IsNull())
1396   {
1397     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1398                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
1399                                 ::LoadCursor (NULL, IDC_ARROW));
1400   }
1401 #endif
1402   return theWClass;
1403 }
1404
1405 //==============================================================================
1406 //function : CreateName
1407 //purpose  : Create numerical name for new object in theMap
1408 //==============================================================================
1409 template <typename ObjectType>
1410 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1411                                     const TCollection_AsciiString& theDefaultString)
1412 {
1413   if (theObjectMap.IsEmpty())
1414     return theDefaultString + TCollection_AsciiString(1);
1415
1416   Standard_Integer aNextKey = 1;
1417   Standard_Boolean isFound = Standard_False;
1418   while (!isFound)
1419   {
1420     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1421     // Look for objects with default names
1422     if (theObjectMap.IsBound1(aStringKey))
1423     {
1424       aNextKey++;
1425     }
1426     else
1427       isFound = Standard_True;
1428   }
1429
1430   return theDefaultString + TCollection_AsciiString(aNextKey);
1431 }
1432
1433 //==============================================================================
1434 //structure : ViewerTest_Names
1435 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
1436 //==============================================================================
1437 struct ViewerTest_Names
1438 {
1439 private:
1440   TCollection_AsciiString myDriverName;
1441   TCollection_AsciiString myViewerName;
1442   TCollection_AsciiString myViewName;
1443
1444 public:
1445
1446   const TCollection_AsciiString& GetDriverName () const
1447   {
1448     return myDriverName;
1449   }
1450   void SetDriverName (const TCollection_AsciiString& theDriverName)
1451   {
1452     myDriverName = theDriverName;
1453   }
1454   const TCollection_AsciiString& GetViewerName () const
1455   {
1456     return myViewerName;
1457   }
1458   void SetViewerName (const TCollection_AsciiString& theViewerName)
1459   {
1460     myViewerName = theViewerName;
1461   }
1462   const TCollection_AsciiString& GetViewName () const
1463   {
1464     return myViewName;
1465   }
1466   void SetViewName (const TCollection_AsciiString& theViewName)
1467   {
1468     myViewName = theViewName;
1469   }
1470
1471   //===========================================================================
1472   //function : Constructor for ViewerTest_Names
1473   //purpose  : Get view, viewer, driver names from custom string
1474   //===========================================================================
1475
1476   ViewerTest_Names (const TCollection_AsciiString& theInputString)
1477   {
1478     TCollection_AsciiString aName(theInputString);
1479     if (theInputString.IsEmpty())
1480     {
1481       // Get current configuration
1482       if (ViewerTest_myDrivers.IsEmpty())
1483         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1484           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1485       else
1486         myDriverName = ViewerTest_myDrivers.Find2
1487         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1488
1489       if(ViewerTest_myContexts.IsEmpty())
1490       {
1491         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1492           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1493       }
1494       else
1495       {
1496         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1497       }
1498
1499       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1500     }
1501     else
1502     {
1503       // There is at least view name
1504       Standard_Integer aParserNumber = 0;
1505       for (Standard_Integer i = 0; i < 3; ++i)
1506       {
1507         Standard_Integer aParserPos = aName.SearchFromEnd("/");
1508         if(aParserPos != -1)
1509         {
1510           aParserNumber++;
1511           aName.Split(aParserPos-1);
1512         }
1513         else
1514           break;
1515       }
1516       if (aParserNumber == 0)
1517       {
1518         // Only view name
1519         if (!ViewerTest::GetAISContext().IsNull())
1520         {
1521           myDriverName = ViewerTest_myDrivers.Find2
1522           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1523           myViewerName = ViewerTest_myContexts.Find2
1524           (ViewerTest::GetAISContext());
1525         }
1526         else
1527         {
1528           // There is no opened contexts here, need to create names for viewer and driver
1529           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1530             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1531
1532           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1533             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1534         }
1535         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1536       }
1537       else if (aParserNumber == 1)
1538       {
1539         // Here is viewerName/viewName
1540         if (!ViewerTest::GetAISContext().IsNull())
1541           myDriverName = ViewerTest_myDrivers.Find2
1542           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1543         else
1544         {
1545           // There is no opened contexts here, need to create name for driver
1546           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1547             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1548         }
1549         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1550
1551         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1552       }
1553       else
1554       {
1555         //Here is driverName/viewerName/viewName
1556         myDriverName = TCollection_AsciiString(aName);
1557
1558         TCollection_AsciiString aViewerName(theInputString);
1559         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1560         myViewerName = TCollection_AsciiString(aViewerName);
1561
1562         myViewName = TCollection_AsciiString(theInputString);
1563       }
1564     }
1565   }
1566 };
1567
1568 //==============================================================================
1569 //function : FindContextByView
1570 //purpose  : Find AIS_InteractiveContext by View
1571 //==============================================================================
1572
1573 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1574 {
1575   Handle(AIS_InteractiveContext) anAISContext;
1576
1577   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1578        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1579   {
1580     if (anIter.Value()->CurrentViewer() == theView->Viewer())
1581        return anIter.Key2();
1582   }
1583   return anAISContext;
1584 }
1585
1586 //==============================================================================
1587 //function : IsWindowOverlapped
1588 //purpose  : Check if theWindow overlapp another view
1589 //==============================================================================
1590
1591 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1592                                      const Standard_Integer thePxTop,
1593                                      const Standard_Integer thePxRight,
1594                                      const Standard_Integer thePxBottom,
1595                                      TCollection_AsciiString& theViewId)
1596 {
1597   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1598       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1599   {
1600     Standard_Integer aTop = 0,
1601       aLeft = 0,
1602       aRight = 0,
1603       aBottom = 0;
1604     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1605     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1606         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1607         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1608         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1609     {
1610       theViewId = anIter.Key1();
1611       return Standard_True;
1612     }
1613   }
1614   return Standard_False;
1615 }
1616
1617 // Workaround: to create and delete non-orthographic views outside ViewerTest
1618 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1619 {
1620   ViewerTest_myViews.UnBind1 (theName);
1621 }
1622
1623 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1624                                const Handle(V3d_View)& theView)
1625 {
1626   ViewerTest_myViews.Bind (theName, theView);
1627 }
1628
1629 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1630 {
1631   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1632 }
1633
1634 //! Auxiliary tool performing continuous redraws of specified window.
1635 class ViewerTest_ContinuousRedrawer
1636 {
1637 public:
1638   //! Return global instance.
1639   static ViewerTest_ContinuousRedrawer& Instance()
1640   {
1641     static ViewerTest_ContinuousRedrawer aRedrawer;
1642     return aRedrawer;
1643   }
1644 public:
1645
1646   //! Destructor.
1647   ~ViewerTest_ContinuousRedrawer()
1648   {
1649     Stop();
1650   }
1651
1652   //! Start thread.
1653   void Start (const Handle(Aspect_Window)& theWindow,
1654               Standard_Real theTargetFps)
1655   {
1656     if (myWindow != theWindow
1657      || myTargetFps != theTargetFps)
1658     {
1659       Stop();
1660       myWindow = theWindow;
1661       myTargetFps = theTargetFps;
1662     }
1663     if (myThread.GetId() == 0)
1664     {
1665       myToStop = false;
1666       myThread.Run (this);
1667     }
1668   }
1669
1670   //! Stop thread.
1671   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1672   {
1673     if (!theWindow.IsNull()
1674       && myWindow != theWindow)
1675     {
1676       return;
1677     }
1678
1679     {
1680       Standard_Mutex::Sentry aLock (myMutex);
1681       myToStop = true;
1682     }
1683     myThread.Wait();
1684     myToStop = false;
1685     myWindow.Nullify();
1686   }
1687
1688 private:
1689
1690   //! Thread loop.
1691   void doThreadLoop()
1692   {
1693     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1694     OSD_Timer aTimer;
1695     aTimer.Start();
1696     Standard_Real aTimeOld = 0.0;
1697     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1698     for (;;)
1699     {
1700       {
1701         Standard_Mutex::Sentry aLock (myMutex);
1702         if (myToStop)
1703         {
1704           return;
1705         }
1706       }
1707       if (myTargetFps > 0.0)
1708       {
1709         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
1710         const Standard_Real aDuration = aTimeNew - aTimeOld;
1711         if (aDuration >= aTargetDur)
1712         {
1713           myWindow->InvalidateContent (aDisp);
1714           aTimeOld = aTimeNew;
1715         }
1716       }
1717       else
1718       {
1719         myWindow->InvalidateContent (aDisp);
1720       }
1721
1722       OSD::MilliSecSleep (1);
1723     }
1724   }
1725
1726   //! Thread creation callback.
1727   static Standard_Address doThreadWrapper (Standard_Address theData)
1728   {
1729     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1730     aThis->doThreadLoop();
1731     return 0;
1732   }
1733
1734   //! Empty constructor.
1735   ViewerTest_ContinuousRedrawer()
1736   : myThread (doThreadWrapper),
1737     myTargetFps (0.0),
1738     myToStop (false) {}
1739
1740 private:
1741   Handle(Aspect_Window) myWindow;
1742   OSD_Thread      myThread;
1743   Standard_Mutex  myMutex;
1744   Standard_Real   myTargetFps;
1745   volatile bool   myToStop;
1746 };
1747
1748 //==============================================================================
1749 //function : ViewerInit
1750 //purpose  : Create the window viewer and initialize all the global variable
1751 //==============================================================================
1752
1753 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1754                                                 const Standard_Integer thePxTop,
1755                                                 const Standard_Integer thePxWidth,
1756                                                 const Standard_Integer thePxHeight,
1757                                                 const TCollection_AsciiString& theViewName,
1758                                                 const TCollection_AsciiString& theDisplayName,
1759                                                 const Handle(V3d_View)& theViewToClone)
1760 {
1761   // Default position and dimension of the viewer window.
1762   // Note that left top corner is set to be sufficiently small to have
1763   // window fit in the small screens (actual for remote desktops, see #23003).
1764   // The position corresponds to the window's client area, thus some
1765   // gap is added for window frame to be visible.
1766   Standard_Integer aPxLeft   = 20;
1767   Standard_Integer aPxTop    = 40;
1768   Standard_Integer aPxWidth  = 409;
1769   Standard_Integer aPxHeight = 409;
1770   Standard_Boolean toCreateViewer = Standard_False;
1771   if (!theViewToClone.IsNull())
1772   {
1773     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1774   }
1775
1776   Handle(OpenGl_GraphicDriver) aGraphicDriver;
1777   ViewerTest_Names aViewNames(theViewName);
1778   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1779     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1780
1781   if (thePxLeft != 0)
1782     aPxLeft = thePxLeft;
1783   if (thePxTop != 0)
1784     aPxTop = thePxTop;
1785   if (thePxWidth != 0)
1786     aPxWidth = thePxWidth;
1787   if (thePxHeight != 0)
1788     aPxHeight = thePxHeight;
1789
1790   // Get graphic driver (create it or get from another view)
1791   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1792   if (isNewDriver)
1793   {
1794     // Get connection string
1795   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1796     if (!theDisplayName.IsEmpty())
1797     {
1798       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1799     }
1800     else
1801     {
1802       ::Display* aDispX = NULL;
1803       // create dedicated display connection instead of reusing Tk connection
1804       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1805       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1806       Tcl_Interp* aTclInterp = aCommands.Interp();
1807       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1808       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1809       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1810     }
1811   #else
1812     (void)theDisplayName; // avoid warning on unused argument
1813     SetDisplayConnection (new Aspect_DisplayConnection ());
1814   #endif
1815
1816     if (Draw_VirtualWindows)
1817     {
1818       // don't waste the time waiting for VSync when window is not displayed on the screen
1819       ViewerTest_myDefaultCaps.swapInterval = 0;
1820       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1821       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1822     }
1823     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
1824     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1825     aGraphicDriver->InitContext();
1826
1827     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1828     toCreateViewer = Standard_True;
1829   }
1830   else
1831   {
1832     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1833   }
1834
1835   //Dispose the window if input parameters are default
1836   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1837   {
1838     Standard_Integer aTop = 0,
1839                      aLeft = 0,
1840                      aRight = 0,
1841                      aBottom = 0,
1842                      aScreenWidth = 0,
1843                      aScreenHeight = 0;
1844
1845     // Get screen resolution
1846 #if defined(_WIN32) || defined(__WIN32__)
1847     RECT aWindowSize;
1848     GetClientRect(GetDesktopWindow(), &aWindowSize);
1849     aScreenHeight = aWindowSize.bottom;
1850     aScreenWidth = aWindowSize.right;
1851 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1852     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1853 #else
1854     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1855     aScreenWidth = WidthOfScreen(aScreen);
1856     aScreenHeight = HeightOfScreen(aScreen);
1857 #endif
1858
1859     TCollection_AsciiString anOverlappedViewId("");
1860
1861     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1862     {
1863       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1864
1865       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1866         && aRight + 2*aPxWidth + 40 > aScreenWidth)
1867       {
1868         if (aBottom + aPxHeight + 40 > aScreenHeight)
1869         {
1870           aPxLeft = 20;
1871           aPxTop = 40;
1872           break;
1873         }
1874         aPxLeft = 20;
1875         aPxTop = aBottom + 40;
1876       }
1877       else
1878         aPxLeft = aRight + 20;
1879     }
1880   }
1881
1882   // Get viewer name
1883   TCollection_AsciiString aTitle("3D View - ");
1884   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1885
1886   // Change name of current active window
1887   if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
1888   {
1889     aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
1890   }
1891
1892   // Create viewer
1893   Handle(V3d_Viewer) a3DViewer;
1894   // If it's the single view, we first look for empty context
1895   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1896   {
1897     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1898       anIter(ViewerTest_myContexts);
1899     if (anIter.More())
1900       ViewerTest::SetAISContext (anIter.Value());
1901     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1902   }
1903   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1904   {
1905     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1906     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1907   }
1908   else if (a3DViewer.IsNull())
1909   {
1910     toCreateViewer = Standard_True;
1911     a3DViewer = new V3d_Viewer(aGraphicDriver);
1912     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1913     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1914                                            ViewerTest_DefaultBackground.GradientColor2,
1915                                            ViewerTest_DefaultBackground.FillMethod);
1916   }
1917
1918   // AIS context setup
1919   if (ViewerTest::GetAISContext().IsNull() ||
1920       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1921   {
1922     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1923     ViewerTest::SetAISContext (aContext);
1924     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1925   }
1926   else
1927   {
1928     ViewerTest::ResetEventManager();
1929   }
1930
1931   // Create window
1932 #if defined(_WIN32)
1933   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1934                                     Handle(WNT_WClass)::DownCast (WClass()),
1935                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1936                                     aPxLeft, aPxTop,
1937                                     aPxWidth, aPxHeight,
1938                                     Quantity_NOC_BLACK);
1939 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1940   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1941                                      aPxLeft, aPxTop,
1942                                      aPxWidth, aPxHeight);
1943   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1944 #else
1945   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1946                                   aTitle.ToCString(),
1947                                   aPxLeft, aPxTop,
1948                                   aPxWidth, aPxHeight);
1949 #endif
1950   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1951
1952   // View setup
1953   Handle(V3d_View) aView;
1954   if (!theViewToClone.IsNull())
1955   {
1956     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1957   }
1958   else
1959   {
1960     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1961   }
1962
1963   aView->SetWindow (VT_GetWindow());
1964   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1965
1966   ViewerTest::CurrentView(aView);
1967   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1968
1969   // Setup for X11 or NT
1970   OSWindowSetup();
1971
1972   // Set parameters for V3d_View and V3d_Viewer
1973   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1974   aV3dView->SetComputedMode(Standard_False);
1975
1976   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1977   if (toCreateViewer)
1978   {
1979     a3DViewer->SetDefaultLights();
1980     a3DViewer->SetLightOn();
1981   }
1982
1983 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1984   if (isNewDriver)
1985   {
1986     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1987     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1988   }
1989 #endif
1990
1991   VT_GetWindow()->Map();
1992
1993   // Set the handle of created view in the event manager
1994   ViewerTest::ResetEventManager();
1995
1996   ViewerTest::CurrentView()->Redraw();
1997
1998   aView.Nullify();
1999   a3DViewer.Nullify();
2000
2001   return aViewNames.GetViewName();
2002 }
2003
2004 //==============================================================================
2005 //function : RedrawAllViews
2006 //purpose  : Redraw all created views
2007 //==============================================================================
2008 void ViewerTest::RedrawAllViews()
2009 {
2010   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2011   for (; aViewIt.More(); aViewIt.Next())
2012   {
2013     const Handle(V3d_View)& aView = aViewIt.Key2();
2014     aView->Redraw();
2015   }
2016 }
2017
2018 //==============================================================================
2019 //function : Vinit
2020 //purpose  : Create the window viewer and initialize all the global variable
2021 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
2022 //==============================================================================
2023
2024 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2025 {
2026   TCollection_AsciiString aViewName, aDisplayName;
2027   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2028   Handle(V3d_View) aCopyFrom;
2029   TCollection_AsciiString aName, aValue;
2030   int is2dMode = -1;
2031   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2032   {
2033     const TCollection_AsciiString anArg = theArgVec[anArgIt];
2034     TCollection_AsciiString anArgCase = anArg;
2035     anArgCase.LowerCase();
2036     if (anArgIt + 1 < theArgsNb
2037      && anArgCase == "-name")
2038     {
2039       aViewName = theArgVec[++anArgIt];
2040     }
2041     else if (anArgIt + 1 < theArgsNb
2042           && (anArgCase == "-left"
2043            || anArgCase == "-l"))
2044     {
2045       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2046     }
2047     else if (anArgIt + 1 < theArgsNb
2048           && (anArgCase == "-top"
2049            || anArgCase == "-t"))
2050     {
2051       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2052     }
2053     else if (anArgIt + 1 < theArgsNb
2054           && (anArgCase == "-width"
2055            || anArgCase == "-w"))
2056     {
2057       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2058     }
2059     else if (anArgIt + 1 < theArgsNb
2060           && (anArgCase == "-height"
2061            || anArgCase == "-h"))
2062     {
2063       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2064     }
2065     else if (anArgCase == "-exitonclose")
2066     {
2067       ViewerTest_EventManager::ToExitOnCloseView() = true;
2068       if (anArgIt + 1 < theArgsNb
2069        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
2070       {
2071         ++anArgIt;
2072       }
2073     }
2074     else if (anArgCase == "-closeonescape"
2075           || anArgCase == "-closeonesc")
2076     {
2077       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
2078       if (anArgIt + 1 < theArgsNb
2079        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
2080       {
2081         ++anArgIt;
2082       }
2083     }
2084     else if (anArgCase == "-2d_mode"
2085           || anArgCase == "-2dmode"
2086           || anArgCase == "-2d")
2087     {
2088       bool toEnable = true;
2089       if (anArgIt + 1 < theArgsNb
2090        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2091       {
2092         ++anArgIt;
2093       }
2094       is2dMode = toEnable ? 1 : 0;
2095     }
2096     else if (anArgIt + 1 < theArgsNb
2097           && (anArgCase == "-disp"
2098            || anArgCase == "-display"))
2099     {
2100       aDisplayName = theArgVec[++anArgIt];
2101     }
2102     else if (!ViewerTest::CurrentView().IsNull()
2103           &&  aCopyFrom.IsNull()
2104           && (anArgCase == "-copy"
2105            || anArgCase == "-clone"
2106            || anArgCase == "-cloneactive"
2107            || anArgCase == "-cloneactiveview"))
2108     {
2109       aCopyFrom = ViewerTest::CurrentView();
2110     }
2111     // old syntax
2112     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2113     {
2114       aName.LowerCase();
2115       if (aName == "name")
2116       {
2117         aViewName = aValue;
2118       }
2119       else if (aName == "l"
2120             || aName == "left")
2121       {
2122         aPxLeft = aValue.IntegerValue();
2123       }
2124       else if (aName == "t"
2125             || aName == "top")
2126       {
2127         aPxTop = aValue.IntegerValue();
2128       }
2129       else if (aName == "disp"
2130             || aName == "display")
2131       {
2132         aDisplayName = aValue;
2133       }
2134       else if (aName == "w"
2135             || aName == "width")
2136       {
2137         aPxWidth = aValue.IntegerValue();
2138       }
2139       else if (aName == "h"
2140             || aName == "height")
2141       {
2142         aPxHeight = aValue.IntegerValue();
2143       }
2144       else
2145       {
2146         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2147         return 1;
2148       }
2149     }
2150     else if (aViewName.IsEmpty())
2151     {
2152       aViewName = anArg;
2153     }
2154     else
2155     {
2156       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2157       return 1;
2158     }
2159   }
2160
2161 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2162   if (!aDisplayName.IsEmpty())
2163   {
2164     aDisplayName.Clear();
2165     std::cout << "Warning: display parameter will be ignored.\n";
2166   }
2167 #endif
2168
2169   ViewerTest_Names aViewNames (aViewName);
2170   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2171   {
2172     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2173     theDi.Eval (aCommand.ToCString());
2174     if (is2dMode != -1)
2175     {
2176       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2177     }
2178     return 0;
2179   }
2180
2181   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2182                                                             aViewName, aDisplayName, aCopyFrom);
2183   if (is2dMode != -1)
2184   {
2185     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2186   }
2187   theDi << aViewId;
2188   return 0;
2189 }
2190
2191 //! Parse HLR algo type.
2192 static Standard_Boolean parseHlrAlgoType (const char* theName,
2193                                           Prs3d_TypeOfHLR& theType)
2194 {
2195   TCollection_AsciiString aName (theName);
2196   aName.LowerCase();
2197   if (aName == "polyalgo")
2198   {
2199     theType = Prs3d_TOH_PolyAlgo;
2200   }
2201   else if (aName == "algo")
2202   {
2203     theType = Prs3d_TOH_Algo;
2204   }
2205   else
2206   {
2207     return Standard_False;
2208   }
2209   return Standard_True;
2210 }
2211
2212 //==============================================================================
2213 //function : VHLR
2214 //purpose  : hidden lines removal algorithm
2215 //==============================================================================
2216
2217 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2218 {
2219   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2220   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2221   if (aView.IsNull())
2222   {
2223     std::cerr << "Error: No opened viewer!\n";
2224     return 1;
2225   }
2226
2227   Standard_Boolean hasHlrOnArg = Standard_False;
2228   Standard_Boolean hasShowHiddenArg = Standard_False;
2229   Standard_Boolean isHLROn = Standard_False;
2230   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2231   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2232   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2233   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2234   {
2235     TCollection_AsciiString anArg (argv[anArgIter]);
2236     anArg.LowerCase();
2237     if (anUpdateTool.parseRedrawMode (anArg))
2238     {
2239       continue;
2240     }
2241     else if (anArg == "-showhidden"
2242           && anArgIter + 1 < argc
2243           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2244     {
2245       ++anArgIter;
2246       hasShowHiddenArg = Standard_True;
2247       continue;
2248     }
2249     else if ((anArg == "-type"
2250            || anArg == "-algo"
2251            || anArg == "-algotype")
2252           && anArgIter + 1 < argc
2253           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2254     {
2255       ++anArgIter;
2256       continue;
2257     }
2258     else if (!hasHlrOnArg
2259           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2260     {
2261       hasHlrOnArg = Standard_True;
2262       continue;
2263     }
2264     // old syntax
2265     else if (!hasShowHiddenArg
2266           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2267     {
2268       hasShowHiddenArg = Standard_True;
2269       continue;
2270     }
2271     else
2272     {
2273       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2274       return 1;
2275     }
2276   }
2277   if (!hasHlrOnArg)
2278   {
2279     di << "HLR:        " << aView->ComputedMode() << "\n";
2280     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2281     di << "HlrAlgo:    ";
2282     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2283     {
2284       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2285       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2286       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2287     }
2288     anUpdateTool.Invalidate();
2289     return 0;
2290   }
2291
2292   Standard_Boolean toRecompute = Standard_False;
2293   if (aTypeOfHLR != Prs3d_TOH_NotSet
2294    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2295   {
2296     toRecompute = Standard_True;
2297     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2298   }
2299   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2300   {
2301     toRecompute = Standard_True;
2302     if (toShowHidden)
2303     {
2304       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2305     }
2306     else
2307     {
2308       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2309     }
2310   }
2311
2312   // redisplay shapes
2313   if (aView->ComputedMode() && isHLROn && toRecompute)
2314   {
2315     AIS_ListOfInteractive aListOfShapes;
2316     aCtx->DisplayedObjects (aListOfShapes);
2317     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2318     {
2319       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2320       {
2321         aCtx->Redisplay (aShape, Standard_False);
2322       }
2323     }
2324   }
2325
2326   aView->SetComputedMode (isHLROn);
2327   return 0;
2328 }
2329
2330 //==============================================================================
2331 //function : VHLRType
2332 //purpose  : change type of using HLR algorithm
2333 //==============================================================================
2334
2335 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2336 {
2337   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2338   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2339   if (aView.IsNull())
2340   {
2341     std::cerr << "Error: No opened viewer!\n";
2342     return 1;
2343   }
2344
2345   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2346   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2347   AIS_ListOfInteractive aListOfShapes;
2348   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2349   {
2350     TCollection_AsciiString anArg (argv[anArgIter]);
2351     anArg.LowerCase();
2352     if (anUpdateTool.parseRedrawMode (anArg))
2353     {
2354       continue;
2355     }
2356     else if ((anArg == "-type"
2357            || anArg == "-algo"
2358            || anArg == "-algotype")
2359           && anArgIter + 1 < argc
2360           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2361     {
2362       ++anArgIter;
2363       continue;
2364     }
2365     // old syntax
2366     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2367           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2368     {
2369       continue;
2370     }
2371     else
2372     {
2373       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2374       TCollection_AsciiString aName (argv[anArgIter]);
2375       if (!aMap.IsBound2 (aName))
2376       {
2377         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2378         return 1;
2379       }
2380
2381       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2382       if (aShape.IsNull())
2383       {
2384         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2385         return 1;
2386       }
2387       aListOfShapes.Append (aShape);
2388       continue;
2389     }
2390   }
2391   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2392   {
2393     std::cout << "Syntax error: wrong number of arguments!\n";
2394     return 1;
2395   }
2396
2397   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2398   if (isGlobal)
2399   {
2400     aCtx->DisplayedObjects (aListOfShapes);
2401     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2402   }
2403
2404   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2405   {
2406     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2407     if (aShape.IsNull())
2408     {
2409       continue;
2410     }
2411
2412     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2413                             && aView->ComputedMode();
2414     if (!isGlobal
2415      || aShape->TypeOfHLR() != aTypeOfHLR)
2416     {
2417       aShape->SetTypeOfHLR (aTypeOfHLR);
2418     }
2419     if (toUpdateShape)
2420     {
2421       aCtx->Redisplay (aShape, Standard_False);
2422     }
2423   }
2424   return 0;
2425 }
2426
2427 //==============================================================================
2428 //function : FindViewIdByWindowHandle
2429 //purpose  : Find theView Id in the map of views by window handle
2430 //==============================================================================
2431 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2432 TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
2433 {
2434   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2435        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2436   {
2437     Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
2438     if (aWindowHandle == theWindowHandle)
2439       return anIter.Key1();
2440   }
2441   return TCollection_AsciiString("");
2442 }
2443 #endif
2444
2445 //! Make the view active
2446 void ActivateView (const TCollection_AsciiString& theViewName,
2447                    Standard_Boolean theToUpdate = Standard_True)
2448 {
2449   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2450   if (aView.IsNull())
2451   {
2452     return;
2453   }
2454
2455   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2456   if (!anAISContext.IsNull())
2457   {
2458     if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
2459     {
2460       aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
2461     }
2462
2463     ViewerTest::CurrentView (aView);
2464     ViewerTest::SetAISContext (anAISContext);
2465     aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
2466 #if defined(_WIN32)
2467     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2468 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2469     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2470 #else
2471     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2472 #endif
2473     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2474     if (theToUpdate)
2475     {
2476       ViewerTest::CurrentView()->Redraw();
2477     }
2478   }
2479 }
2480
2481 //==============================================================================
2482 //function : RemoveView
2483 //purpose  :
2484 //==============================================================================
2485 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2486                              const Standard_Boolean  theToRemoveContext)
2487 {
2488   if (!ViewerTest_myViews.IsBound2 (theView))
2489   {
2490     return;
2491   }
2492
2493   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2494   RemoveView (aViewName, theToRemoveContext);
2495 }
2496
2497 //==============================================================================
2498 //function : RemoveView
2499 //purpose  : Close and remove view from display, clear maps if neccessary
2500 //==============================================================================
2501 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2502 {
2503   if (!ViewerTest_myViews.IsBound1(theViewName))
2504   {
2505     std::cout << "Wrong view name\n";
2506     return;
2507   }
2508
2509   // Activate another view if it's active now
2510   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2511   {
2512     if (ViewerTest_myViews.Extent() > 1)
2513     {
2514       TCollection_AsciiString aNewViewName;
2515       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2516            anIter.More(); anIter.Next())
2517       {
2518         if (anIter.Key1() != theViewName)
2519         {
2520           aNewViewName = anIter.Key1();
2521           break;
2522         }
2523       }
2524       ActivateView (aNewViewName);
2525     }
2526     else
2527     {
2528       VT_GetWindow().Nullify();
2529       ViewerTest::CurrentView (Handle(V3d_View)());
2530       if (isContextRemoved)
2531       {
2532         Handle(AIS_InteractiveContext) anEmptyContext;
2533         ViewerTest::SetAISContext(anEmptyContext);
2534       }
2535     }
2536   }
2537
2538   // Delete view
2539   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2540   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2541   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2542   aRedrawer.Stop (aView->Window());
2543
2544   // Remove view resources
2545   ViewerTest_myViews.UnBind1(theViewName);
2546   aView->Window()->Unmap();
2547   aView->Remove();
2548
2549 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2550   XFlush (GetDisplayConnection()->GetDisplay());
2551 #endif
2552
2553   // Keep context opened only if the closed view is last to avoid
2554   // unused empty contexts
2555   if (!aCurrentContext.IsNull())
2556   {
2557     // Check if there are more difined views in the viewer
2558     aCurrentContext->CurrentViewer()->InitDefinedViews();
2559     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2560     {
2561       // Remove driver if there is no viewers that use it
2562       Standard_Boolean isRemoveDriver = Standard_True;
2563       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2564           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2565       {
2566         if (aCurrentContext != anIter.Key2() &&
2567           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2568         {
2569           isRemoveDriver = Standard_False;
2570           break;
2571         }
2572       }
2573
2574       aCurrentContext->RemoveAll (Standard_False);
2575       if(isRemoveDriver)
2576       {
2577         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2578       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2579         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2580       #endif
2581       }
2582
2583       ViewerTest_myContexts.UnBind2(aCurrentContext);
2584     }
2585   }
2586   std::cout << "3D View - " << theViewName << " was deleted.\n";
2587   if (ViewerTest_EventManager::ToExitOnCloseView())
2588   {
2589     Draw_Interprete ("exit");
2590   }
2591 }
2592
2593 //==============================================================================
2594 //function : VClose
2595 //purpose  : Remove the view defined by its name
2596 //==============================================================================
2597
2598 static int VClose (Draw_Interpretor& /*theDi*/,
2599                    Standard_Integer  theArgsNb,
2600                    const char**      theArgVec)
2601 {
2602   NCollection_List<TCollection_AsciiString> aViewList;
2603   if (theArgsNb > 1)
2604   {
2605     TCollection_AsciiString anArg (theArgVec[1]);
2606     anArg.UpperCase();
2607     if (anArg.IsEqual ("ALL")
2608      || anArg.IsEqual ("*"))
2609     {
2610       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2611            anIter.More(); anIter.Next())
2612       {
2613         aViewList.Append (anIter.Key1());
2614       }
2615       if (aViewList.IsEmpty())
2616       {
2617         std::cout << "No view to close\n";
2618         return 0;
2619       }
2620     }
2621     else
2622     {
2623       ViewerTest_Names aViewName (theArgVec[1]);
2624       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2625       {
2626         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2627         return 1;
2628       }
2629       aViewList.Append (aViewName.GetViewName());
2630     }
2631   }
2632   else
2633   {
2634     // close active view
2635     if (ViewerTest::CurrentView().IsNull())
2636     {
2637       std::cerr << "No active view!\n";
2638       return 1;
2639     }
2640     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2641   }
2642
2643   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2644   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2645        anIter.More(); anIter.Next())
2646   {
2647     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2648   }
2649
2650   return 0;
2651 }
2652
2653 //==============================================================================
2654 //function : VActivate
2655 //purpose  : Activate the view defined by its ID
2656 //==============================================================================
2657
2658 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2659 {
2660   if (theArgsNb == 1)
2661   {
2662     theDi.Eval("vviewlist");
2663     return 0;
2664   }
2665
2666   TCollection_AsciiString aNameString;
2667   Standard_Boolean toUpdate = Standard_True;
2668   Standard_Boolean toActivate = Standard_True;
2669   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2670   {
2671     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2672     anArg.LowerCase();
2673     if (toUpdate
2674      && anArg == "-noupdate")
2675     {
2676       toUpdate = Standard_False;
2677     }
2678     else if (toActivate
2679           && aNameString.IsEmpty()
2680           && anArg == "none")
2681     {
2682       ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2683       VT_GetWindow().Nullify();
2684       ViewerTest::CurrentView (Handle(V3d_View)());
2685       ViewerTest::ResetEventManager();
2686       theDi << theArgVec[0] << ": all views are inactive\n";
2687       toActivate = Standard_False;
2688     }
2689     else if (toActivate
2690           && aNameString.IsEmpty())
2691     {
2692       aNameString = theArgVec[anArgIter];
2693     }
2694     else
2695     {
2696       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2697       return 1;
2698     }
2699   }
2700
2701   if (!toActivate)
2702   {
2703     return 0;
2704   }
2705   else if (aNameString.IsEmpty())
2706   {
2707     std::cout << "Syntax error: wrong number of arguments\n";
2708     return 1;
2709   }
2710
2711   // Check if this view exists in the viewer with the driver
2712   ViewerTest_Names aViewNames (aNameString);
2713   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2714   {
2715     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2716     return 1;
2717   }
2718
2719   // Check if it is active already
2720   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2721   {
2722     theDi << theArgVec[0] << ": the view is active already\n";
2723     return 0;
2724   }
2725
2726   ActivateView (aViewNames.GetViewName(), toUpdate);
2727   return 0;
2728 }
2729
2730 //==============================================================================
2731 //function : VViewList
2732 //purpose  : Print current list of views per viewer and graphic driver ID
2733 //           shared between viewers
2734 //==============================================================================
2735
2736 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2737 {
2738   if (theArgsNb > 2)
2739   {
2740     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2741           << "Usage: " << theArgVec[0] << " name";
2742     return 1;
2743   }
2744   if (ViewerTest_myContexts.Size() < 1)
2745     return 0;
2746
2747   Standard_Boolean isTreeView =
2748     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2749
2750   if (isTreeView)
2751   {
2752     theDi << theArgVec[0] <<":\n";
2753   }
2754
2755   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2756        aDriverIter.More(); aDriverIter.Next())
2757   {
2758     if (isTreeView)
2759       theDi << aDriverIter.Key1() << ":\n";
2760
2761     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2762       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2763     {
2764       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2765       {
2766         if (isTreeView)
2767         {
2768           TCollection_AsciiString aContextName(aContextIter.Key1());
2769           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2770         }
2771
2772         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2773              aViewIter.More(); aViewIter.Next())
2774         {
2775           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2776           {
2777             TCollection_AsciiString aViewName(aViewIter.Key1());
2778             if (isTreeView)
2779             {
2780               if (aViewIter.Value() == ViewerTest::CurrentView())
2781                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2782               else
2783                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2784             }
2785             else
2786             {
2787               theDi << aViewName << " ";
2788             }
2789           }
2790         }
2791       }
2792     }
2793   }
2794   return 0;
2795 }
2796
2797 //==============================================================================
2798 //function : GetMousePosition
2799 //purpose  :
2800 //==============================================================================
2801 void ViewerTest::GetMousePosition (Standard_Integer& theX,
2802                                    Standard_Integer& theY)
2803 {
2804   if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
2805   {
2806     theX = aViewCtrl->LastMousePosition().x();
2807     theY = aViewCtrl->LastMousePosition().y();
2808   }
2809 }
2810
2811 //==============================================================================
2812 //function : VViewProj
2813 //purpose  : Switch view projection
2814 //==============================================================================
2815 static int VViewProj (Draw_Interpretor& ,
2816                       Standard_Integer theNbArgs,
2817                       const char** theArgVec)
2818 {
2819   static Standard_Boolean isYup = Standard_False;
2820   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2821   if (aView.IsNull())
2822   {
2823     std::cout << "Error: no active view\n";
2824     return 1;
2825   }
2826
2827   TCollection_AsciiString aCmdName (theArgVec[0]);
2828   Standard_Boolean isGeneralCmd = Standard_False;
2829   if (aCmdName == "vfront")
2830   {
2831     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2832   }
2833   else if (aCmdName == "vback")
2834   {
2835     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2836   }
2837   else if (aCmdName == "vtop")
2838   {
2839     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2840   }
2841   else if (aCmdName == "vbottom")
2842   {
2843     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2844   }
2845   else if (aCmdName == "vleft")
2846   {
2847     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2848   }
2849   else if (aCmdName == "vright")
2850   {
2851     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2852   }
2853   else if (aCmdName == "vaxo")
2854   {
2855     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2856   }
2857   else
2858   {
2859     isGeneralCmd = Standard_True;
2860     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2861     {
2862       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2863       anArgCase.LowerCase();
2864       if (anArgCase == "-zup")
2865       {
2866         isYup = Standard_False;
2867       }
2868       else if (anArgCase == "-yup")
2869       {
2870         isYup = Standard_True;
2871       }
2872       else if (anArgCase == "-front"
2873             || anArgCase == "front"
2874             || anArgCase == "-f"
2875             || anArgCase == "f")
2876       {
2877         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2878       }
2879       else if (anArgCase == "-back"
2880             || anArgCase == "back"
2881             || anArgCase == "-b"
2882             || anArgCase == "b")
2883       {
2884         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2885       }
2886       else if (anArgCase == "-top"
2887             || anArgCase == "top"
2888             || anArgCase == "-t"
2889             || anArgCase == "t")
2890       {
2891         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2892       }
2893       else if (anArgCase == "-bottom"
2894             || anArgCase == "bottom"
2895             || anArgCase == "-bot"
2896             || anArgCase == "bot"
2897             || anArgCase == "-b"
2898             || anArgCase == "b")
2899       {
2900         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2901       }
2902       else if (anArgCase == "-left"
2903             || anArgCase == "left"
2904             || anArgCase == "-l"
2905             || anArgCase == "l")
2906       {
2907         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2908       }
2909       else if (anArgCase == "-right"
2910             || anArgCase == "right"
2911             || anArgCase == "-r"
2912             || anArgCase == "r")
2913       {
2914         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2915       }
2916       else if (anArgCase == "-axoleft"
2917             || anArgCase == "-leftaxo"
2918             || anArgCase == "axoleft"
2919             || anArgCase == "leftaxo")
2920       {
2921         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2922       }
2923       else if (anArgCase == "-axo"
2924             || anArgCase == "axo"
2925             || anArgCase == "-a"
2926             || anArgCase == "a"
2927             || anArgCase == "-axoright"
2928             || anArgCase == "-rightaxo"
2929             || anArgCase == "axoright"
2930             || anArgCase == "rightaxo")
2931       {
2932         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2933       }
2934       else if (anArgCase == "+x")
2935       {
2936         aView->SetProj (V3d_Xpos, isYup);
2937       }
2938       else if (anArgCase == "-x")
2939       {
2940         aView->SetProj (V3d_Xneg, isYup);
2941       }
2942       else if (anArgCase == "+y")
2943       {
2944         aView->SetProj (V3d_Ypos, isYup);
2945       }
2946       else if (anArgCase == "-y")
2947       {
2948         aView->SetProj (V3d_Yneg, isYup);
2949       }
2950       else if (anArgCase == "+z")
2951       {
2952         aView->SetProj (V3d_Zpos, isYup);
2953       }
2954       else if (anArgCase == "-z")
2955       {
2956         aView->SetProj (V3d_Zneg, isYup);
2957       }
2958       else if (anArgCase == "+x+y+z")
2959       {
2960         aView->SetProj (V3d_XposYposZpos, isYup);
2961       }
2962       else if (anArgCase == "+x+y-z")
2963       {
2964         aView->SetProj (V3d_XposYposZneg, isYup);
2965       }
2966       else if (anArgCase == "+x-y+z")
2967       {
2968         aView->SetProj (V3d_XposYnegZpos, isYup);
2969       }
2970       else if (anArgCase == "+x-y-z")
2971       {
2972         aView->SetProj (V3d_XposYnegZneg, isYup);
2973       }
2974       else if (anArgCase == "-x+y+z")
2975       {
2976         aView->SetProj (V3d_XnegYposZpos, isYup);
2977       }
2978       else if (anArgCase == "-x+y-z")
2979       {
2980         aView->SetProj (V3d_XnegYposZneg, isYup);
2981       }
2982       else if (anArgCase == "-x-y+z")
2983       {
2984         aView->SetProj (V3d_XnegYnegZpos, isYup);
2985       }
2986       else if (anArgCase == "-x-y-z")
2987       {
2988         aView->SetProj (V3d_XnegYnegZneg, isYup);
2989       }
2990       else if (anArgCase == "+x+y")
2991       {
2992         aView->SetProj (V3d_XposYpos, isYup);
2993       }
2994       else if (anArgCase == "+x-y")
2995       {
2996         aView->SetProj (V3d_XposYneg, isYup);
2997       }
2998       else if (anArgCase == "-x+y")
2999       {
3000         aView->SetProj (V3d_XnegYpos, isYup);
3001       }
3002       else if (anArgCase == "-x-y")
3003       {
3004         aView->SetProj (V3d_XnegYneg, isYup);
3005       }
3006       else if (anArgCase == "+x+z")
3007       {
3008         aView->SetProj (V3d_XposZpos, isYup);
3009       }
3010       else if (anArgCase == "+x-z")
3011       {
3012         aView->SetProj (V3d_XposZneg, isYup);
3013       }
3014       else if (anArgCase == "-x+z")
3015       {
3016         aView->SetProj (V3d_XnegZpos, isYup);
3017       }
3018       else if (anArgCase == "-x-z")
3019       {
3020         aView->SetProj (V3d_XnegZneg, isYup);
3021       }
3022       else if (anArgCase == "+y+z")
3023       {
3024         aView->SetProj (V3d_YposZpos, isYup);
3025       }
3026       else if (anArgCase == "+y-z")
3027       {
3028         aView->SetProj (V3d_YposZneg, isYup);
3029       }
3030       else if (anArgCase == "-y+z")
3031       {
3032         aView->SetProj (V3d_YnegZpos, isYup);
3033       }
3034       else if (anArgCase == "-y-z")
3035       {
3036         aView->SetProj (V3d_YnegZneg, isYup);
3037       }
3038       else if (anArgIter + 1 < theNbArgs
3039             && anArgCase == "-frame"
3040             && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3041       {
3042         TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3043         aFrameDef.LowerCase();
3044         gp_Dir aRight, anUp;
3045         if (aFrameDef.Value (2) == aFrameDef.Value (4))
3046         {
3047           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3048           return 1;
3049         }
3050
3051         if (aFrameDef.Value (2) == 'x')
3052         {
3053           aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3054         }
3055         else if (aFrameDef.Value (2) == 'y')
3056         {
3057           aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3058         }
3059         else if (aFrameDef.Value (2) == 'z')
3060         {
3061           aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3062         }
3063         else
3064         {
3065           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3066           return 1;
3067         }
3068
3069         if (aFrameDef.Value (4) == 'x')
3070         {
3071           anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3072         }
3073         else if (aFrameDef.Value (4) == 'y')
3074         {
3075           anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3076         }
3077         else if (aFrameDef.Value (4) == 'z')
3078         {
3079           anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3080         }
3081         else
3082         {
3083           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3084           return 1;
3085         }
3086
3087         const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3088         const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3089         const gp_Dir aDir = anUp.Crossed (aRight);
3090         aCamera->SetCenter (gp_Pnt (0, 0, 0));
3091         aCamera->SetDirection (aDir);
3092         aCamera->SetUp (anUp);
3093         aCamera->OrthogonalizeUp();
3094
3095         aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3096         aView->Update();
3097       }
3098       else
3099       {
3100         std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3101         return 1;
3102       }
3103     }
3104   }
3105
3106   if (!isGeneralCmd
3107     && theNbArgs != 1)
3108   {
3109     std::cout << "Syntax error: wrong number of arguments\n";
3110     return 1;
3111   }
3112   return 0;
3113 }
3114
3115 //==============================================================================
3116 //function : VHelp
3117 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
3118 //Draw arg : No args
3119 //==============================================================================
3120
3121 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3122 {
3123   di << "=========================\n";
3124   di << "F : FitAll\n";
3125   di << "T : TopView\n";
3126   di << "B : BottomView\n";
3127   di << "R : RightView\n";
3128   di << "L : LeftView\n";
3129   di << "A : AxonometricView\n";
3130   di << "D : ResetView\n";
3131
3132   di << "=========================\n";
3133   di << "S : Shading\n";
3134   di << "W : Wireframe\n";
3135   di << "H : HiddenLineRemoval\n";
3136   di << "U : Unset display mode\n";
3137   di << "Delete : Remove selection from viewer\n";
3138
3139   di << "=========================\n";
3140   di << "Selection mode \n";
3141   di << "0 : Shape\n";
3142   di << "1 : Vertex\n";
3143   di << "2 : Edge\n";
3144   di << "3 : Wire\n";
3145   di << "4 : Face\n";
3146   di << "5 : Shell\n";
3147   di << "6 : Solid\n";
3148   di << "7 : Compound\n";
3149
3150   di << "=========================\n";
3151   di << "< : Hilight next detected\n";
3152   di << "> : Hilight previous detected\n";
3153
3154   return 0;
3155 }
3156
3157 #ifdef _WIN32
3158
3159 static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3160                                            UINT theMsg,
3161                                            WPARAM wParam,
3162                                            LPARAM lParam )
3163 {
3164   if (ViewerTest_myViews.IsEmpty())
3165   {
3166     return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3167   }
3168
3169   switch (theMsg)
3170   {
3171     case WM_CLOSE:
3172     {
3173       // Delete view from map of views
3174       ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3175       return 0;
3176     }
3177     case WM_ACTIVATE:
3178     {
3179       if (LOWORD(wParam) == WA_CLICKACTIVE
3180        || LOWORD(wParam) == WA_ACTIVE
3181        || ViewerTest::CurrentView().IsNull())
3182       {
3183         // Activate inactive window
3184         if (VT_GetWindow().IsNull()
3185          || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3186         {
3187           ActivateView (FindViewIdByWindowHandle (theWinHandle));
3188         }
3189       }
3190       break;
3191     }
3192     default:
3193     {
3194       return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3195     }
3196   }
3197   return 0;
3198 }
3199
3200 static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3201                                         UINT theMsg,
3202                                         WPARAM wParam,
3203                                         LPARAM lParam)
3204 {
3205   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3206   if (aView.IsNull())
3207   {
3208     return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3209   }
3210
3211   switch (theMsg)
3212   {
3213     case WM_PAINT:
3214     {
3215       PAINTSTRUCT aPaint;
3216       BeginPaint(theWinHandle, &aPaint);
3217       EndPaint  (theWinHandle, &aPaint);
3218       ViewerTest::CurrentEventManager()->ProcessExpose();
3219       break;
3220     }
3221     case WM_SIZE:
3222     {
3223       ViewerTest::CurrentEventManager()->ProcessConfigure();
3224       break;
3225     }
3226     case WM_MOVE:
3227     case WM_MOVING:
3228     case WM_SIZING:
3229     {
3230       switch (aView->RenderingParams().StereoMode)
3231       {
3232         case Graphic3d_StereoMode_RowInterlaced:
3233         case Graphic3d_StereoMode_ColumnInterlaced:
3234         case Graphic3d_StereoMode_ChessBoard:
3235         {
3236           // track window moves to reverse stereo pair
3237           aView->MustBeResized();
3238           aView->Update();
3239           break;
3240         }
3241         default:
3242           break;
3243       }
3244       break;
3245     }
3246     case WM_KEYUP:
3247     case WM_KEYDOWN:
3248     {
3249       const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3250       if (aVKey != Aspect_VKey_UNKNOWN)
3251       {
3252         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3253         if (theMsg == WM_KEYDOWN)
3254         {
3255           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3256         }
3257         else
3258         {
3259           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3260         }
3261         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3262       }
3263       break;
3264     }
3265     case WM_LBUTTONUP:
3266     case WM_MBUTTONUP:
3267     case WM_RBUTTONUP:
3268     case WM_LBUTTONDOWN:
3269     case WM_MBUTTONDOWN:
3270     case WM_RBUTTONDOWN:
3271     {
3272       const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3273       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3274       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3275       switch (theMsg)
3276       {
3277         case WM_LBUTTONUP:
3278         case WM_LBUTTONDOWN:
3279           aButton = Aspect_VKeyMouse_LeftButton;
3280           break;
3281         case WM_MBUTTONUP:
3282         case WM_MBUTTONDOWN:
3283           aButton = Aspect_VKeyMouse_MiddleButton;
3284           break;
3285         case WM_RBUTTONUP:
3286         case WM_RBUTTONDOWN:
3287           aButton = Aspect_VKeyMouse_RightButton;
3288           break;
3289       }
3290       if (theMsg == WM_LBUTTONDOWN
3291        || theMsg == WM_MBUTTONDOWN
3292        || theMsg == WM_RBUTTONDOWN)
3293       {
3294         if (aButton == Aspect_VKeyMouse_LeftButton)
3295         {
3296           TheIsAnimating = Standard_False;
3297         }
3298
3299         SetFocus  (theWinHandle);
3300         SetCapture(theWinHandle);
3301         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3302       }
3303       else
3304       {
3305         ReleaseCapture();
3306         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3307       }
3308       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3309       break;
3310     }
3311     case WM_MOUSEWHEEL:
3312     {
3313       const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3314       const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3315       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3316       Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3317       POINT aCursorPnt = { aPos.x(), aPos.y() };
3318       if (ScreenToClient (theWinHandle, &aCursorPnt))
3319       {
3320         aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3321       }
3322
3323       ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3324       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3325       break;
3326     }
3327     case WM_MOUSEMOVE:
3328     {
3329       Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3330       Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3331       Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(wParam);
3332
3333       // don't make a slide-show from input events - fetch the actual mouse cursor position
3334       CURSORINFO aCursor;
3335       aCursor.cbSize = sizeof(aCursor);
3336       if (::GetCursorInfo (&aCursor) != FALSE)
3337       {
3338         POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3339         if (ScreenToClient (theWinHandle, &aCursorPnt))
3340         {
3341           // as we override mouse position, we need overriding also mouse state
3342           aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3343           aButtons = WNT_Window::MouseButtonsAsync();
3344           aFlags   = WNT_Window::MouseKeyFlagsAsync();
3345         }
3346       }
3347
3348       if (VT_GetWindow().IsNull()
3349       || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3350       {
3351         // mouse move events come also for inactive windows
3352         break;
3353       }
3354
3355       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3356       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
3357       break;
3358     }
3359     default:
3360     {
3361       return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3362     }
3363   }
3364   return 0L;
3365 }
3366
3367 //==============================================================================
3368 //function : ViewerMainLoop
3369 //purpose  : Get a Event on the view and dispatch it
3370 //==============================================================================
3371
3372 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3373 {
3374   Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
3375   if (aViewCtrl.IsNull()
3376    || theNbArgs < 4)
3377   {
3378     return 0;
3379   }
3380
3381   aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3382
3383   std::cout << "Start picking\n";
3384
3385   MSG aMsg;
3386   aMsg.wParam = 1;
3387   while (aViewCtrl->ToPickPoint())
3388   {
3389     // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3390     if (GetMessageW (&aMsg, NULL, 0, 0))
3391     {
3392       TranslateMessage (&aMsg);
3393       DispatchMessageW (&aMsg);
3394     }
3395   }
3396
3397   std::cout << "Picking done\n";
3398   return 0;
3399 }
3400
3401 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3402
3403 int min( int a, int b )
3404 {
3405   if( a<b )
3406     return a;
3407   else
3408     return b;
3409 }
3410
3411 int max( int a, int b )
3412 {
3413   if( a>b )
3414     return a;
3415   else
3416     return b;
3417 }
3418
3419 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3420 {
3421   static XEvent aReport;
3422   const Standard_Boolean toPick = theNbArgs > 0;
3423   if (theNbArgs > 0)
3424   {
3425     if (ViewerTest::CurrentEventManager().IsNull())
3426     {
3427       return 0;
3428     }
3429     ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3430   }
3431
3432   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3433   XNextEvent (aDisplay, &aReport);
3434
3435   // Handle event for the chosen display connection
3436   switch (aReport.type)
3437   {
3438     case ClientMessage:
3439     {
3440       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3441       {
3442         // Close the window
3443         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3444         return toPick ? 0 : 1;
3445       }
3446       break;
3447     }
3448     case FocusIn:
3449     {
3450       // Activate inactive view
3451       Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3452       if (aWindow != aReport.xfocus.window)
3453       {
3454         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3455       }
3456       break;
3457     }
3458     case Expose:
3459     {
3460       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3461       if (anXWindow == aReport.xexpose.window)
3462       {
3463         ViewerTest::CurrentEventManager()->ProcessExpose();
3464       }
3465
3466       // remove all the ExposureMask and process them at once
3467       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3468       {
3469         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3470         {
3471           break;
3472         }
3473       }
3474
3475       break;
3476     }
3477     case ConfigureNotify:
3478     {
3479       // remove all the StructureNotifyMask and process them at once
3480       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3481       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3482       {
3483         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3484         {
3485           break;
3486         }
3487       }
3488
3489       if (anXWindow == aReport.xconfigure.window)
3490       {
3491         ViewerTest::CurrentEventManager()->ProcessConfigure();
3492       }
3493       break;
3494     }
3495     case KeyPress:
3496     case KeyRelease:
3497     {
3498       XKeyEvent*   aKeyEvent = (XKeyEvent* )&aReport;
3499       const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
3500       const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
3501       if (aVKey != Aspect_VKey_UNKNOWN)
3502       {
3503         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3504         if (aReport.type == KeyPress)
3505         {
3506           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3507         }
3508         else
3509         {
3510           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3511         }
3512         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3513       }
3514       break;
3515     }
3516     case ButtonPress:
3517     case ButtonRelease:
3518     {
3519       const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
3520       Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3521       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3522       if (aReport.xbutton.button == Button1)
3523       {
3524         aButton = Aspect_VKeyMouse_LeftButton;
3525       }
3526       if (aReport.xbutton.button == Button2)
3527       {
3528         aButton = Aspect_VKeyMouse_MiddleButton;
3529       }
3530       if (aReport.xbutton.button == Button3)
3531       {
3532         aButton = Aspect_VKeyMouse_RightButton;
3533       }
3534
3535       if (aReport.xbutton.state & ControlMask)
3536       {
3537         aFlags |= Aspect_VKeyFlags_CTRL;
3538       }
3539       if (aReport.xbutton.state & ShiftMask)
3540       {
3541         aFlags |= Aspect_VKeyFlags_SHIFT;
3542       }
3543       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3544       {
3545         aFlags |= Aspect_VKeyFlags_ALT;
3546       }
3547
3548       if (aReport.xbutton.button == Button4
3549        || aReport.xbutton.button == Button5)
3550       {
3551         if (aReport.type != ButtonPress)
3552         {
3553           break;
3554         }
3555
3556         const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
3557         ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3558       }
3559       else if (aReport.type == ButtonPress)
3560       {
3561         if (aButton == Aspect_VKeyMouse_LeftButton)
3562         {
3563           TheIsAnimating = Standard_False;
3564         }
3565         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3566       }
3567       else
3568       {
3569         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3570       }
3571       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3572       break;
3573     }
3574     case MotionNotify:
3575     {
3576       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3577       if (anXWindow != aReport.xmotion.window)
3578       {
3579         break;
3580       }
3581
3582       // remove all the ButtonMotionMask and process them at once
3583       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3584       {
3585         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3586         {
3587           break;
3588         }
3589       }
3590
3591       Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
3592       Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
3593       Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
3594       if ((aReport.xmotion.state & Button1Mask) != 0)
3595       {
3596         aButtons |= Aspect_VKeyMouse_LeftButton;
3597       }
3598       else if ((aReport.xmotion.state & Button2Mask) != 0)
3599       {
3600         aButtons |= Aspect_VKeyMouse_MiddleButton;
3601       }
3602       else if ((aReport.xmotion.state & Button3Mask) != 0)
3603       {
3604         aButtons |= Aspect_VKeyMouse_RightButton;
3605       }
3606
3607       if (aReport.xmotion.state & ControlMask)
3608       {
3609         aFlags |= Aspect_VKeyFlags_CTRL;
3610       }
3611       if (aReport.xmotion.state & ShiftMask)
3612       {
3613         aFlags |= Aspect_VKeyFlags_SHIFT;
3614       }
3615       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3616       {
3617         aFlags |= Aspect_VKeyFlags_ALT;
3618       }
3619
3620       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3621       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3622       break;
3623     }
3624   }
3625   return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
3626 }
3627
3628 //==============================================================================
3629 //function : VProcessEvents
3630 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3631 //==============================================================================
3632 static void VProcessEvents (ClientData theDispX, int)
3633 {
3634   Display* aDispX = (Display* )theDispX;
3635   Handle(Aspect_DisplayConnection) aDispConn;
3636   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3637        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3638   {
3639     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3640     if (aDispConnTmp->GetDisplay() == aDispX)
3641     {
3642       aDispConn = aDispConnTmp;
3643       break;
3644     }
3645   }
3646   if (aDispConn.IsNull())
3647   {
3648     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3649     return;
3650   }
3651
3652   // process new events in queue
3653   SetDisplayConnection (aDispConn);
3654   int aNbRemain = 0;
3655   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3656   {
3657     const int anEventResult = ViewerMainLoop (0, NULL);
3658     if (anEventResult == 0)
3659     {
3660       return;
3661     }
3662
3663     aNbRemain = XPending (aDispX);
3664     if (++anEventIter >= aNbEventsMax
3665      || aNbRemain <= 0)
3666     {
3667       break;
3668     }
3669   }
3670
3671   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3672   // it is possible that new events will arrive to queue before the end of this callback
3673   // so that either this callback should go into an infinite loop (blocking processing of other events)
3674   // or to keep unprocessed events till the next queue update (which can arrive not soon).
3675   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3676   if (aNbRemain != 0)
3677   {
3678     XEvent aDummyEvent;
3679     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3680     aDummyEvent.type = ClientMessage;
3681     aDummyEvent.xclient.format = 32;
3682     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3683     XFlush (aDispX);
3684   }
3685
3686   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3687   {
3688     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3689   }
3690 }
3691 #endif
3692
3693 //==============================================================================
3694 //function : OSWindowSetup
3695 //purpose  : Setup for the X11 window to be able to cath the event
3696 //==============================================================================
3697
3698
3699 static void OSWindowSetup()
3700 {
3701 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
3702   // X11
3703
3704   Window  window   = VT_GetWindow()->XWindow();
3705   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
3706   Display *aDisplay = GetDisplayConnection()->GetDisplay();
3707   XSynchronize(aDisplay, 1);
3708
3709   // X11 : For keyboard on SUN
3710   XWMHints wmhints;
3711   wmhints.flags = InputHint;
3712   wmhints.input = 1;
3713
3714   XSetWMHints( aDisplay, window, &wmhints);
3715
3716   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask | KeyReleaseMask |
3717     ButtonPressMask | ButtonReleaseMask |
3718     StructureNotifyMask |
3719     PointerMotionMask |
3720     Button1MotionMask | Button2MotionMask |
3721     Button3MotionMask | FocusChangeMask
3722     );
3723   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3724   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3725
3726   XSynchronize(aDisplay, 0);
3727
3728 #else
3729   // _WIN32
3730 #endif
3731
3732 }
3733
3734 //==============================================================================
3735 //function : VFit
3736 //purpose  :
3737 //==============================================================================
3738
3739 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3740 {
3741   const Handle(V3d_View) aView = ViewerTest::CurrentView();
3742   if (aView.IsNull())
3743   {
3744     std::cout << "Error: no active viewer!\n";
3745     return 1;
3746   }
3747
3748   Standard_Boolean toFit = Standard_True;
3749   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3750   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3751   {
3752     TCollection_AsciiString anArg (theArgv[anArgIter]);
3753     anArg.LowerCase();
3754     if (anUpdateTool.parseRedrawMode (anArg))
3755     {
3756       continue;
3757     }
3758     else if (anArg == "-selected")
3759     {
3760       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3761       toFit = Standard_False;
3762     }
3763     else
3764     {
3765       std::cout << "Syntax error at '" << anArg << "'\n";
3766     }
3767   }
3768
3769   if (toFit)
3770   {
3771     aView->FitAll (0.01, Standard_False);
3772   }
3773   return 0;
3774 }
3775
3776 //=======================================================================
3777 //function : VFitArea
3778 //purpose  : Fit view to show area located between two points
3779 //         : given in world 2D or 3D coordinates.
3780 //=======================================================================
3781 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
3782 {
3783   Handle(V3d_View) aView = ViewerTest::CurrentView();
3784   if (aView.IsNull())
3785   {
3786     std::cerr << theArgVec[0] << "Error: No active view.\n";
3787     return 1;
3788   }
3789
3790   // Parse arguments.
3791   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3792   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3793
3794   if (theArgNb == 5)
3795   {
3796     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3797     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3798     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3799     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3800   }
3801   else if (theArgNb == 7)
3802   {
3803     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3804     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3805     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3806     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3807     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3808     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3809   }
3810   else
3811   {
3812     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3813     theDI.PrintHelp(theArgVec[0]);
3814     return 1;
3815   }
3816
3817   // Convert model coordinates to view space
3818   Handle(Graphic3d_Camera) aCamera = aView->Camera();
3819   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3820   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3821
3822   // Determine fit area
3823   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3824   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3825
3826   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3827
3828   if (aDiagonal < Precision::Confusion())
3829   {
3830     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3831     return 1;
3832   }
3833
3834   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3835   return 0;
3836 }
3837
3838 //==============================================================================
3839 //function : VZFit
3840 //purpose  : ZFitall, no DRAW arguments
3841 //Draw arg : No args
3842 //==============================================================================
3843 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3844 {
3845   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3846
3847   if (aCurrentView.IsNull())
3848   {
3849     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3850     return 1;
3851   }
3852
3853   if (theArgsNb == 1)
3854   {
3855     aCurrentView->ZFitAll();
3856     aCurrentView->Redraw();
3857     return 0;
3858   }
3859
3860   Standard_Real aScale = 1.0;
3861
3862   if (theArgsNb >= 2)
3863   {
3864     aScale = Draw::Atoi (theArgVec[1]);
3865   }
3866
3867   aCurrentView->ZFitAll (aScale);
3868   aCurrentView->Redraw();
3869
3870   return 0;
3871 }
3872
3873 //==============================================================================
3874 //function : VRepaint
3875 //purpose  :
3876 //==============================================================================
3877 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3878 {
3879   Handle(V3d_View) aView = ViewerTest::CurrentView();
3880   if (aView.IsNull())
3881   {
3882     std::cout << "Error: no active viewer!\n";
3883     return 1;
3884   }
3885
3886   Standard_Boolean isImmediateUpdate = Standard_False;
3887   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3888   {
3889     TCollection_AsciiString anArg (theArgVec[anArgIter]);
3890     anArg.LowerCase();
3891     if (anArg == "-immediate"
3892      || anArg == "-imm")
3893     {
3894       isImmediateUpdate = Standard_True;
3895       if (anArgIter + 1 < theArgNb
3896        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3897       {
3898         ++anArgIter;
3899       }
3900     }
3901     else if (anArg == "-continuous"
3902           || anArg == "-cont"
3903           || anArg == "-fps"
3904           || anArg == "-framerate")
3905     {
3906       Standard_Real aFps = -1.0;
3907       if (anArgIter + 1 < theArgNb
3908        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3909       {
3910         aFps = Draw::Atof (theArgVec[++anArgIter]);
3911       }
3912
3913       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3914       if (Abs (aFps) >= 1.0)
3915       {
3916         aRedrawer.Start (aView->Window(), aFps);
3917       }
3918       else
3919       {
3920         aRedrawer.Stop();
3921       }
3922     }
3923     else
3924     {
3925       std::cout << "Syntax error at '" << anArg << "'\n";
3926       return 1;
3927     }
3928   }
3929
3930   if (isImmediateUpdate)
3931   {
3932     aView->RedrawImmediate();
3933   }
3934   else
3935   {
3936     aView->Redraw();
3937   }
3938   return 0;
3939 }
3940
3941 //==============================================================================
3942 //function : VClear
3943 //purpose  : Remove all the object from the viewer
3944 //Draw arg : No args
3945 //==============================================================================
3946
3947 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3948 {
3949   Handle(V3d_View) V = ViewerTest::CurrentView();
3950   if(!V.IsNull())
3951     ViewerTest::Clear();
3952   return 0;
3953 }
3954
3955 //==============================================================================
3956 //function : VPick
3957 //purpose  :
3958 //==============================================================================
3959
3960 static int VPick (Draw_Interpretor& ,
3961                   Standard_Integer theNbArgs,
3962                   const char** theArgVec)
3963 {
3964   if (ViewerTest::CurrentView().IsNull())
3965   {
3966     return 1;
3967   }
3968
3969   if (theNbArgs < 4)
3970   {
3971     std::cout << "Syntax error: Invalid number of arguments\n";
3972     return 1;
3973   }
3974
3975   while (ViewerMainLoop (theNbArgs, theArgVec))
3976   {
3977     //
3978   }
3979
3980   return 0;
3981 }
3982
3983 namespace
3984 {
3985
3986   //! Changes the background
3987   //! @param theDrawInterpretor the interpreter of the Draw Harness application
3988   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
3989   //! @param theCommandLineArguments the array of command line arguments
3990   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
3991   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
3992                           const Standard_Integer theNumberOfCommandLineArguments,
3993                           const char** const     theCommandLineArguments)
3994   {
3995     if (theNumberOfCommandLineArguments < 1)
3996     {
3997       return TCL_ERROR;
3998     }
3999     BackgroundChanger aBackgroundChanger;
4000     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
4001                                                 theNumberOfCommandLineArguments,
4002                                                 theCommandLineArguments))
4003     {
4004       theDrawInterpretor << "Wrong command arguments.\n"
4005                             "Type 'help "
4006                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
4007       return TCL_ERROR;
4008     }
4009     return TCL_OK;
4010   }
4011
4012 } // namespace
4013
4014 //==============================================================================
4015 //function : VScale
4016 //purpose  : View Scaling
4017 //==============================================================================
4018
4019 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
4020 {
4021   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4022   if ( V3dView.IsNull() ) return 1;
4023
4024   if ( argc != 4 ) {
4025     di << argv[0] << "Invalid number of arguments\n";
4026     return 1;
4027   }
4028   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
4029   return 0;
4030 }
4031 //==============================================================================
4032 //function : VZBuffTrihedron
4033 //purpose  :
4034 //==============================================================================
4035
4036 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
4037                             Standard_Integer  theArgNb,
4038                             const char**      theArgVec)
4039 {
4040   Handle(V3d_View) aView = ViewerTest::CurrentView();
4041   if (aView.IsNull())
4042   {
4043     std::cout << "Error: no active viewer!\n";
4044     return 1;
4045   }
4046
4047   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
4048
4049   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
4050   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
4051   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
4052   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
4053   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
4054   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
4055   Standard_Real                 aScale        = 0.1;
4056   Standard_Real                 aSizeRatio    = 0.8;
4057   Standard_Real                 anArrowDiam   = 0.05;
4058   Standard_Integer              aNbFacets     = 12;
4059   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4060   {
4061     Standard_CString        anArg = theArgVec[anArgIter];
4062     TCollection_AsciiString aFlag (anArg);
4063     aFlag.LowerCase();
4064     if (anUpdateTool.parseRedrawMode (aFlag))
4065     {
4066       continue;
4067     }
4068     else if (aFlag == "-on")
4069     {
4070       continue;
4071     }
4072     else if (aFlag == "-off")
4073     {
4074       aView->TriedronErase();
4075       return 0;
4076     }
4077     else if (aFlag == "-pos"
4078           || aFlag == "-position"
4079           || aFlag == "-corner")
4080     {
4081       if (++anArgIter >= theArgNb)
4082       {
4083         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4084         return 1;
4085       }
4086
4087       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
4088       aPosName.LowerCase();
4089       if (aPosName == "center")
4090       {
4091         aPosition = Aspect_TOTP_CENTER;
4092       }
4093       else if (aPosName == "left_lower"
4094             || aPosName == "lower_left"
4095             || aPosName == "leftlower"
4096             || aPosName == "lowerleft")
4097       {
4098         aPosition = Aspect_TOTP_LEFT_LOWER;
4099       }
4100       else if (aPosName == "left_upper"
4101             || aPosName == "upper_left"
4102             || aPosName == "leftupper"
4103             || aPosName == "upperleft")
4104       {
4105         aPosition = Aspect_TOTP_LEFT_UPPER;
4106       }
4107       else if (aPosName == "right_lower"
4108             || aPosName == "lower_right"
4109             || aPosName == "rightlower"
4110             || aPosName == "lowerright")
4111       {
4112         aPosition = Aspect_TOTP_RIGHT_LOWER;
4113       }
4114       else if (aPosName == "right_upper"
4115             || aPosName == "upper_right"
4116             || aPosName == "rightupper"
4117             || aPosName == "upperright")
4118       {
4119         aPosition = Aspect_TOTP_RIGHT_UPPER;
4120       }
4121       else
4122       {
4123         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
4124         return 1;
4125       }
4126     }
4127     else if (aFlag == "-type")
4128     {
4129       if (++anArgIter >= theArgNb)
4130       {
4131         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4132         return 1;
4133       }
4134
4135       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
4136       aTypeName.LowerCase();
4137       if (aTypeName == "wireframe"
4138        || aTypeName == "wire")
4139       {
4140         aVisType = V3d_WIREFRAME;
4141       }
4142       else if (aTypeName == "zbuffer"
4143             || aTypeName == "shaded")
4144       {
4145         aVisType = V3d_ZBUFFER;
4146       }
4147       else
4148       {
4149         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
4150       }
4151     }
4152     else if (aFlag == "-scale")
4153     {
4154       if (++anArgIter >= theArgNb)
4155       {
4156         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4157         return 1;
4158       }
4159
4160       aScale = Draw::Atof (theArgVec[anArgIter]);
4161     }
4162     else if (aFlag == "-size"
4163           || aFlag == "-sizeratio")
4164     {
4165       if (++anArgIter >= theArgNb)
4166       {
4167         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4168         return 1;
4169       }
4170
4171       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4172     }
4173     else if (aFlag == "-arrowdiam"
4174           || aFlag == "-arrowdiameter")
4175     {
4176       if (++anArgIter >= theArgNb)
4177       {
4178         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4179         return 1;
4180       }
4181
4182       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4183     }
4184     else if (aFlag == "-nbfacets")
4185     {
4186       if (++anArgIter >= theArgNb)
4187       {
4188         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4189         return 1;
4190       }
4191
4192       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4193     }
4194     else if (aFlag == "-colorlabel"
4195           || aFlag == "-colorlabels")
4196     {
4197       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4198                                                            theArgVec + anArgIter + 1,
4199                                                            aLabelsColor);
4200       if (aNbParsed == 0)
4201       {
4202         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4203         return 1;
4204       }
4205       anArgIter += aNbParsed;
4206     }
4207     else if (aFlag == "-colorarrowx")
4208     {
4209       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4210                                                            theArgVec + anArgIter + 1,
4211                                                            anArrowColorX);
4212       if (aNbParsed == 0)
4213       {
4214         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4215         return 1;
4216       }
4217       anArgIter += aNbParsed;
4218     }
4219     else if (aFlag == "-colorarrowy")
4220     {
4221       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4222                                                            theArgVec + anArgIter + 1,
4223                                                            anArrowColorY);
4224       if (aNbParsed == 0)
4225       {
4226         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4227         return 1;
4228       }
4229       anArgIter += aNbParsed;
4230     }
4231     else if (aFlag == "-colorarrowz")
4232     {
4233       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4234                                                            theArgVec + anArgIter + 1,
4235                                                            anArrowColorZ);
4236       if (aNbParsed == 0)
4237       {
4238         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4239         return 1;
4240       }
4241       anArgIter += aNbParsed;
4242     }
4243     else
4244     {
4245       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4246       return 1;
4247     }
4248   }
4249
4250   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4251                                aSizeRatio, anArrowDiam, aNbFacets);
4252   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4253   aView->ZFitAll();
4254   return 0;
4255 }
4256
4257 //==============================================================================
4258 //function : VRotate
4259 //purpose  : Camera Rotating
4260 //==============================================================================
4261
4262 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4263 {
4264   Handle(V3d_View) aView = ViewerTest::CurrentView();
4265   if (aView.IsNull())
4266   {
4267     std::cout << "No active view!\n";
4268     return 1;
4269   }
4270
4271   Standard_Boolean hasFlags = Standard_False;
4272   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4273   {
4274     Standard_CString        anArg (theArgVec[anArgIter]);
4275     TCollection_AsciiString aFlag (anArg);
4276     aFlag.LowerCase();
4277     if (aFlag == "-mousestart"
4278      || aFlag == "-mousefrom")
4279     {
4280       hasFlags = Standard_True;
4281       if (anArgIter + 2 >= theArgNb)
4282       {
4283         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4284         return 1;
4285       }
4286
4287       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4288       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4289       aView->StartRotation (anX, anY);
4290     }
4291     else if (aFlag == "-mousemove")
4292     {
4293       hasFlags = Standard_True;
4294       if (anArgIter + 2 >= theArgNb)
4295       {
4296         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4297         return 1;
4298       }
4299
4300       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4301       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4302       aView->Rotation (anX, anY);
4303     }
4304     else if (theArgNb != 4
4305           && theArgNb != 7)
4306     {
4307       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4308       return 1;
4309     }
4310   }
4311
4312   if (hasFlags)
4313   {
4314     return 0;
4315   }
4316   else if (theArgNb == 4)
4317   {
4318     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4319     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4320     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4321     aView->Rotate (anAX, anAY, anAZ);
4322     return 0;
4323   }
4324   else if (theArgNb == 7)
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
4330     Standard_Real anX = Draw::Atof (theArgVec[4]);
4331     Standard_Real anY = Draw::Atof (theArgVec[5]);
4332     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4333
4334     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4335     return 0;
4336   }
4337
4338   std::cout << "Error: Invalid number of arguments\n";
4339   return 1;
4340 }
4341
4342 //==============================================================================
4343 //function : VZoom
4344 //purpose  : View zoom in / out (relative to current zoom)
4345 //==============================================================================
4346
4347 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4348   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4349   if ( V3dView.IsNull() ) {
4350     return 1;
4351   }
4352
4353   if ( argc == 2 ) {
4354     Standard_Real coef = Draw::Atof(argv[1]);
4355     if ( coef <= 0.0 ) {
4356       di << argv[1] << "Invalid value\n";
4357       return 1;
4358     }
4359     V3dView->SetZoom( Draw::Atof(argv[1]) );
4360     return 0;
4361   } else {
4362     di << argv[0] << " Invalid number of arguments\n";
4363     return 1;
4364   }
4365 }
4366
4367 //==============================================================================
4368 //function : VPan
4369 //purpose  : View panning (in pixels)
4370 //==============================================================================
4371
4372 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4373   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4374   if ( V3dView.IsNull() ) return 1;
4375
4376   if ( argc == 3 ) {
4377     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4378     return 0;
4379   } else {
4380     di << argv[0] << " Invalid number of arguments\n";
4381     return 1;
4382   }
4383 }
4384
4385 //==============================================================================
4386 //function : VPlace
4387 //purpose  : Place the point (in pixels) at the center of the window
4388 //==============================================================================
4389 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4390 {
4391   Handle(V3d_View) aView = ViewerTest::CurrentView();
4392   if (aView.IsNull())
4393   {
4394     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4395     return 1;
4396   }
4397
4398   if (theArgNb != 3)
4399   {
4400     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4401     return 1;
4402   }
4403
4404   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4405
4406   return 0;
4407 }
4408
4409 static int VColorScale (Draw_Interpretor& theDI,
4410                         Standard_Integer  theArgNb,
4411                         const char**      theArgVec)
4412 {
4413   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4414   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4415   if (aContext.IsNull())
4416   {
4417     std::cout << "Error: no active view!\n";
4418     return 1;
4419   }
4420   if (theArgNb <= 1)
4421   {
4422     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4423     return 1;
4424   }
4425
4426   Handle(AIS_ColorScale) aColorScale;
4427   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4428   {
4429     // find existing object
4430     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4431     if (aColorScale.IsNull())
4432     {
4433       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4434       return 1;
4435     }
4436   }
4437
4438   if (theArgNb <= 2)
4439   {
4440     if (aColorScale.IsNull())
4441     {
4442       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4443       return 1;
4444     }
4445
4446     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4447           << "Min range: "            << aColorScale->GetMin() << "\n"
4448           << "Max range: "            << aColorScale->GetMax() << "\n"
4449           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4450           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4451           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4452           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4453           << "Label position: ";
4454     switch (aColorScale->GetLabelPosition())
4455     {
4456       case Aspect_TOCSP_NONE:
4457         theDI << "None\n";
4458         break;
4459       case Aspect_TOCSP_LEFT:
4460         theDI << "Left\n";
4461         break;
4462       case Aspect_TOCSP_RIGHT:
4463         theDI << "Right\n";
4464         break;
4465       case Aspect_TOCSP_CENTER:
4466         theDI << "Center\n";
4467         break;
4468     }
4469     return 0;
4470   }
4471
4472   if (aColorScale.IsNull())
4473   {
4474     aColorScale = new AIS_ColorScale();
4475     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4476     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4477   }
4478
4479   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4480   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4481   {
4482     Standard_CString        anArg = theArgVec[anArgIter];
4483     TCollection_AsciiString aFlag (anArg);
4484     aFlag.LowerCase();
4485     if (anUpdateTool.parseRedrawMode (aFlag))
4486     {
4487       continue;
4488     }
4489     else if (aFlag == "-range")
4490     {
4491       if (anArgIter + 3 >= theArgNb)
4492       {
4493         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4494         return 1;
4495       }
4496
4497       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
4498       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
4499       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
4500       if (!aRangeMin.IsRealValue()
4501        || !aRangeMax.IsRealValue())
4502       {
4503         std::cout << "Error: the range values should be real!\n";
4504         return 1;
4505       }
4506       else if (!aNbIntervals.IsIntegerValue())
4507       {
4508         std::cout << "Error: the number of intervals should be integer!\n";
4509         return 1;
4510       }
4511
4512       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4513       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4514     }
4515     else if (aFlag == "-font")
4516     {
4517       if (anArgIter + 1 >= theArgNb)
4518       {
4519         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4520         return 1;
4521       }
4522       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4523       if (!aFontArg.IsIntegerValue())
4524       {
4525         std::cout << "Error: HeightFont value should be integer!\n";
4526         return 1;
4527       }
4528
4529       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4530       anArgIter += 1;
4531     }
4532     else if (aFlag == "-textpos")
4533     {
4534       if (anArgIter + 1 >= theArgNb)
4535       {
4536         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4537         return 1;
4538       }
4539
4540       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4541       aTextPosArg.LowerCase();
4542       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4543       if (aTextPosArg == "none")
4544       {
4545         aLabPosition = Aspect_TOCSP_NONE;
4546       }
4547       else if (aTextPosArg == "left")
4548       {
4549         aLabPosition = Aspect_TOCSP_LEFT;
4550       }
4551       else if (aTextPosArg == "right")
4552       {
4553         aLabPosition = Aspect_TOCSP_RIGHT;
4554       }
4555       else if (aTextPosArg == "center")
4556       {
4557         aLabPosition = Aspect_TOCSP_CENTER;
4558       }
4559       else
4560       {
4561         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4562         return 1;
4563       }
4564       aColorScale->SetLabelPosition (aLabPosition);
4565     }
4566     else if (aFlag == "-logarithmic"
4567           || aFlag == "-log")
4568     {
4569       if (anArgIter + 1 >= theArgNb)
4570       {
4571         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4572         return 1;
4573       }
4574
4575       Standard_Boolean IsLog;
4576       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4577       {
4578         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4579         return 1;
4580       }
4581       aColorScale->SetLogarithmic (IsLog);
4582     }
4583     else if (aFlag == "-huerange"
4584           || aFlag == "-hue")
4585     {
4586       if (anArgIter + 2 >= theArgNb)
4587       {
4588         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4589         return 1;
4590       }
4591
4592       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4593       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4594       aColorScale->SetHueRange (aHueMin, aHueMax);
4595     }
4596     else if (aFlag == "-colorrange")
4597     {
4598       Quantity_Color aColorMin, aColorMax;
4599       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4600                                                             theArgVec + (anArgIter + 1),
4601                                                             aColorMin);
4602       anArgIter += aNbParsed1;
4603       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4604                                                             theArgVec + (anArgIter + 1),
4605                                                             aColorMax);
4606       anArgIter += aNbParsed2;
4607       if (aNbParsed1 == 0
4608        || aNbParsed2 == 0)
4609       {
4610         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4611         return 1;
4612       }
4613
4614       aColorScale->SetColorRange (aColorMin, aColorMax);
4615     }
4616     else if (aFlag == "-reversed"
4617           || aFlag == "-inverted"
4618           || aFlag == "-topdown"
4619           || aFlag == "-bottomup")
4620     {
4621       Standard_Boolean toEnable = Standard_True;
4622       if (anArgIter + 1 < theArgNb
4623        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4624       {
4625         ++anArgIter;
4626       }
4627       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4628     }
4629     else if (aFlag == "-smooth"
4630           || aFlag == "-smoothtransition")
4631     {
4632       Standard_Boolean toEnable = Standard_True;
4633       if (anArgIter + 1 < theArgNb
4634        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4635       {
4636         ++anArgIter;
4637       }
4638       aColorScale->SetSmoothTransition (toEnable);
4639     }
4640     else if (aFlag == "-xy")
4641     {
4642       if (anArgIter + 2 >= theArgNb)
4643       {
4644         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4645         return 1;
4646       }
4647
4648       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4649       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4650       if (!anX.IsIntegerValue()
4651        || !anY.IsIntegerValue())
4652       {
4653         std::cout << "Error: coordinates should be integer values!\n";
4654         return 1;
4655       }
4656
4657       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4658     }
4659     else if (aFlag == "-width"
4660           || aFlag == "-w"
4661           || aFlag == "-breadth")
4662     {
4663       if (anArgIter + 1 >= theArgNb)
4664       {
4665         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4666         return 1;
4667       }
4668
4669       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4670       if (!aBreadth.IsIntegerValue())
4671       {
4672         std::cout << "Error: a width should be an integer value!\n";
4673         return 1;
4674       }
4675       aColorScale->SetBreadth (aBreadth.IntegerValue());
4676     }
4677     else if (aFlag == "-height"
4678           || aFlag == "-h")
4679     {
4680       if (anArgIter + 1 >= theArgNb)
4681       {
4682         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4683         return 1;
4684       }
4685
4686       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4687       if (!aHeight.IsIntegerValue())
4688       {
4689         std::cout << "Error: a width should be an integer value!\n";
4690         return 1;
4691       }
4692       aColorScale->SetHeight (aHeight.IntegerValue());
4693     }
4694     else if (aFlag == "-color")
4695     {
4696       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4697       {
4698         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4699         return 1;
4700       }
4701       else if (anArgIter + 2 >= theArgNb)
4702       {
4703         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4704         return 1;
4705       }
4706
4707       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4708       if (!anInd.IsIntegerValue())
4709       {
4710         std::cout << "Error: Index value should be integer!\n";
4711         return 1;
4712       }
4713       const Standard_Integer anIndex = anInd.IntegerValue();
4714       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4715       {
4716         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4717         return 1;
4718       }
4719
4720       Quantity_Color aColor;
4721       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4722                                                            theArgVec + (anArgIter + 1),
4723                                                            aColor);
4724       if (aNbParsed == 0)
4725       {
4726         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4727         return 1;
4728       }
4729       aColorScale->SetIntervalColor (aColor, anIndex);
4730       aColorScale->SetColorType (Aspect_TOCSD_USER);
4731       anArgIter += aNbParsed;
4732     }
4733     else if (aFlag == "-label")
4734     {
4735       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4736       {
4737         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4738         return 1;
4739       }
4740       else if (anArgIter + 2 >= theArgNb)
4741       {
4742         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4743         return 1;
4744       }
4745
4746       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4747       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4748       {
4749         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4750         return 1;
4751       }
4752
4753       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4754       aColorScale->SetLabel     (aText, anIndex);
4755       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4756       anArgIter += 2;
4757     }
4758     else if (aFlag == "-labelat"
4759           || aFlag == "-labat"
4760           || aFlag == "-labelatborder"
4761           || aFlag == "-labatborder"
4762           || aFlag == "-labelatcenter"
4763           || aFlag == "-labatcenter")
4764     {
4765       Standard_Boolean toEnable = Standard_True;
4766       if (aFlag == "-labelat"
4767        || aFlag == "-labat")
4768       {
4769         Standard_Integer aLabAtBorder = -1;
4770         if (++anArgIter >= theArgNb)
4771         {
4772           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4773           anAtBorder.LowerCase();
4774           if (anAtBorder == "border")
4775           {
4776             aLabAtBorder = 1;
4777           }
4778           else if (anAtBorder == "center")
4779           {
4780             aLabAtBorder = 0;
4781           }
4782         }
4783         if (aLabAtBorder == -1)
4784         {
4785           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4786           return 1;
4787         }
4788         toEnable = (aLabAtBorder == 1);
4789       }
4790       else if (anArgIter + 1 < theArgNb
4791             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4792       {
4793         ++anArgIter;
4794       }
4795       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4796                                   || aFlag == "-labatcenter"
4797                                    ? !toEnable
4798                                    :  toEnable);
4799     }
4800     else if (aFlag == "-colors")
4801     {
4802       Aspect_SequenceOfColor aSeq;
4803       for (;;)
4804       {
4805         Quantity_Color aColor;
4806         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4807                                                              theArgVec + (anArgIter + 1),
4808                                                              aColor);
4809         if (aNbParsed == 0)
4810         {
4811           break;
4812         }
4813         anArgIter += aNbParsed;
4814         aSeq.Append (aColor);
4815       }
4816       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4817       {
4818         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4819                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4820         return 1;
4821       }
4822
4823       aColorScale->SetColors    (aSeq);
4824       aColorScale->SetColorType (Aspect_TOCSD_USER);
4825     }
4826     else if (aFlag == "-labels"
4827           || aFlag == "-freelabels")
4828     {
4829       if (anArgIter + 1 >= theArgNb)
4830       {
4831         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4832         return 1;
4833       }
4834
4835       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4836                                  ? aColorScale->GetNumberOfIntervals() + 1
4837                                  : aColorScale->GetNumberOfIntervals();
4838       if (aFlag == "-freelabels")
4839       {
4840         ++anArgIter;
4841         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4842       }
4843       if (anArgIter + aNbLabels >= theArgNb)
4844       {
4845         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4846         return 1;
4847       }
4848
4849       TColStd_SequenceOfExtendedString aSeq;
4850       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4851       {
4852         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4853       }
4854       aColorScale->SetLabels (aSeq);
4855       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4856     }
4857     else if (aFlag == "-title")
4858     {
4859       if (anArgIter + 1 >= theArgNb)
4860       {
4861         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4862         return 1;
4863       }
4864
4865       Standard_Boolean isTwoArgs = Standard_False;
4866       if (anArgIter + 2 < theArgNb)
4867       {
4868         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4869         aSecondArg.LowerCase();
4870       Standard_DISABLE_DEPRECATION_WARNINGS
4871         if (aSecondArg == "none")
4872         {
4873           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4874           isTwoArgs = Standard_True;
4875         }
4876         else if (aSecondArg == "left")
4877         {
4878           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4879           isTwoArgs = Standard_True;
4880         }
4881         else if (aSecondArg == "right")
4882         {
4883           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4884           isTwoArgs = Standard_True;
4885         }
4886         else if (aSecondArg == "center")
4887         {
4888           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4889           isTwoArgs = Standard_True;
4890         }
4891       Standard_ENABLE_DEPRECATION_WARNINGS
4892       }
4893
4894       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4895       if (isTwoArgs)
4896       {
4897         anArgIter += 1;
4898       }
4899       anArgIter += 1;
4900     }
4901     else if (aFlag == "-demoversion"
4902           || aFlag == "-demo")
4903     {
4904       aColorScale->SetPosition (0, 0);
4905       aColorScale->SetTextHeight (16);
4906       aColorScale->SetRange (0.0, 100.0);
4907       aColorScale->SetNumberOfIntervals (10);
4908       aColorScale->SetBreadth (0);
4909       aColorScale->SetHeight  (0);
4910       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4911       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4912       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4913     }
4914     else if (aFlag == "-findcolor")
4915     {
4916       if (anArgIter + 1 >= theArgNb)
4917       {
4918         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4919         return 1;
4920       }
4921
4922       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4923
4924       if (!anArg1.IsRealValue())
4925       {
4926         std::cout << "Error: the value should be real!\n";
4927         return 1;
4928       }
4929
4930       Quantity_Color aColor;
4931       aColorScale->FindColor (anArg1.RealValue(), aColor);
4932       theDI << Quantity_Color::StringName (aColor.Name());
4933       return 0;
4934     }
4935     else
4936     {
4937       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4938       return 1;
4939     }
4940   }
4941
4942   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4943   aView->Window()->Size (aWinWidth, aWinHeight);
4944   if (aColorScale->GetBreadth() == 0)
4945   {
4946     aColorScale->SetBreadth (aWinWidth);
4947   }
4948   if (aColorScale->GetHeight() == 0)
4949   {
4950     aColorScale->SetHeight (aWinHeight);
4951   }
4952   aColorScale->SetToUpdate();
4953   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4954   return 0;
4955 }
4956
4957 //==============================================================================
4958 //function : VGraduatedTrihedron
4959 //purpose  : Displays or hides a graduated trihedron
4960 //==============================================================================
4961 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4962                                   Quantity_Color& theColor)
4963 {
4964   Quantity_NameOfColor aColorName;
4965   TCollection_AsciiString aVal = theValue;
4966   aVal.UpperCase();
4967   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4968   {
4969     return Standard_False;
4970   }
4971   theColor = Quantity_Color (aColorName);
4972   return Standard_True;
4973 }
4974
4975 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4976 {
4977   if (theArgNum < 2)
4978   {
4979     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4980               << theArgs[0] <<"' for more information.\n";
4981     return 1;  //TCL_ERROR
4982   }
4983
4984   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4985   TCollection_AsciiString aParseKey;
4986   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4987   {
4988     TCollection_AsciiString anArg (theArgs [anArgIt]);
4989
4990     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4991     {
4992       aParseKey = anArg;
4993       aParseKey.Remove (1);
4994       aParseKey.LowerCase();
4995       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4996       continue;
4997     }
4998
4999     if (aParseKey.IsEmpty())
5000     {
5001       continue;
5002     }
5003
5004     aMapOfArgs(aParseKey)->Append (anArg);
5005   }
5006
5007   // Check parameters
5008   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
5009        aMapIt.More(); aMapIt.Next())
5010   {
5011     const TCollection_AsciiString& aKey = aMapIt.Key();
5012     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
5013
5014     // Bool key, without arguments
5015     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
5016         && anArgs->IsEmpty())
5017     {
5018       continue;
5019     }
5020
5021     // One argument
5022     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
5023           && anArgs->Length() == 1)
5024     {
5025       continue;
5026     }
5027
5028     // On/off arguments
5029     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
5030         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
5031         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
5032         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
5033         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
5034     {
5035       continue;
5036     }
5037
5038     // One string argument
5039     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
5040           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
5041           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5042     {
5043       continue;
5044     }
5045
5046     // One integer argument
5047     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
5048           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
5049           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
5050           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
5051          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
5052     {
5053       continue;
5054     }
5055
5056     // One real argument
5057     if ( aKey.IsEqual ("arrowlength")
5058          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
5059     {
5060       continue;
5061     }
5062
5063     // Two string arguments
5064     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
5065          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
5066     {
5067       continue;
5068     }
5069
5070     TCollection_AsciiString aLowerKey;
5071     aLowerKey  = "-";
5072     aLowerKey += aKey;
5073     aLowerKey.LowerCase();
5074     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
5075     std::cout << "Type help for more information.\n";
5076     return 1;
5077   }
5078
5079   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
5080   if (anAISContext.IsNull())
5081   {
5082     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
5083     return 1;
5084   }
5085
5086   Standard_Boolean toDisplay = Standard_True;
5087   Quantity_Color aColor;
5088   Graphic3d_GraduatedTrihedron aTrihedronData;
5089   // Process parameters
5090   Handle(TColStd_HSequenceOfAsciiString) aValues;
5091   if (aMapOfArgs.Find ("off", aValues))
5092   {
5093     toDisplay = Standard_False;
5094   }
5095
5096   // AXES NAMES
5097   if (aMapOfArgs.Find ("xname", aValues))
5098   {
5099     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
5100   }
5101   if (aMapOfArgs.Find ("yname", aValues))
5102   {
5103     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
5104   }
5105   if (aMapOfArgs.Find ("zname", aValues))
5106   {
5107     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
5108   }
5109   if (aMapOfArgs.Find ("xdrawname", aValues))
5110   {
5111     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5112   }
5113   if (aMapOfArgs.Find ("ydrawname", aValues))
5114   {
5115     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5116   }
5117   if (aMapOfArgs.Find ("zdrawname", aValues))
5118   {
5119     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
5120   }
5121   if (aMapOfArgs.Find ("xnameoffset", aValues))
5122   {
5123     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5124   }
5125   if (aMapOfArgs.Find ("ynameoffset", aValues))
5126   {
5127     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5128   }
5129   if (aMapOfArgs.Find ("znameoffset", aValues))
5130   {
5131     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
5132   }
5133
5134   // COLORS
5135   if (aMapOfArgs.Find ("xnamecolor", aValues))
5136   {
5137     if (!GetColor (aValues->Value(1), aColor))
5138     {
5139       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
5140       return 1;
5141     }
5142     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
5143   }
5144   if (aMapOfArgs.Find ("ynamecolor", aValues))
5145   {
5146     if (!GetColor (aValues->Value(1), aColor))
5147     {
5148       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
5149       return 1;
5150     }
5151     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
5152   }
5153   if (aMapOfArgs.Find ("znamecolor", aValues))
5154   {
5155     if (!GetColor (aValues->Value(1), aColor))
5156     {
5157       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
5158       return 1;
5159     }
5160     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
5161   }
5162   if (aMapOfArgs.Find ("xcolor", aValues))
5163   {
5164     if (!GetColor (aValues->Value(1), aColor))
5165     {
5166       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5167       return 1;
5168     }
5169     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5170   }
5171   if (aMapOfArgs.Find ("ycolor", aValues))
5172   {
5173     if (!GetColor (aValues->Value(1), aColor))
5174     {
5175       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5176       return 1;
5177     }
5178     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5179   }
5180   if (aMapOfArgs.Find ("zcolor", aValues))
5181   {
5182     if (!GetColor (aValues->Value(1), aColor))
5183     {
5184       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5185       return 1;
5186     }
5187     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5188   }
5189
5190   // TICKMARKS
5191   if (aMapOfArgs.Find ("xticks", aValues))
5192   {
5193     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5194   }
5195   if (aMapOfArgs.Find ("yticks", aValues))
5196   {
5197     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5198   }
5199   if (aMapOfArgs.Find ("zticks", aValues))
5200   {
5201     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5202   }
5203   if (aMapOfArgs.Find ("xticklength", aValues))
5204   {
5205     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5206   }
5207   if (aMapOfArgs.Find ("yticklength", aValues))
5208   {
5209     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5210   }
5211   if (aMapOfArgs.Find ("zticklength", aValues))
5212   {
5213     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5214   }
5215   if (aMapOfArgs.Find ("xdrawticks", aValues))
5216   {
5217     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5218   }
5219   if (aMapOfArgs.Find ("ydrawticks", aValues))
5220   {
5221     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5222   }
5223   if (aMapOfArgs.Find ("zdrawticks", aValues))
5224   {
5225     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5226   }
5227
5228   // VALUES
5229   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5230   {
5231     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5232   }
5233   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5234   {
5235     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5236   }
5237   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5238   {
5239     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5240   }
5241   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5242   {
5243     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5244   }
5245   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5246   {
5247     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5248   }
5249   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5250   {
5251     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5252   }
5253
5254   // ARROWS
5255   if (aMapOfArgs.Find ("arrowlength", aValues))
5256   {
5257     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5258   }
5259
5260   // FONTS
5261   if (aMapOfArgs.Find ("namefont", aValues))
5262   {
5263     aTrihedronData.SetNamesFont (aValues->Value(1));
5264   }
5265   if (aMapOfArgs.Find ("valuesfont", aValues))
5266   {
5267     aTrihedronData.SetValuesFont (aValues->Value(1));
5268   }
5269
5270   if (aMapOfArgs.Find ("drawgrid", aValues))
5271   {
5272     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5273   }
5274   if (aMapOfArgs.Find ("drawaxes", aValues))
5275   {
5276     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5277   }
5278
5279   // The final step: display of erase trihedron
5280   if (toDisplay)
5281   {
5282     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5283   }
5284   else
5285   {
5286     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5287   }
5288
5289   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5290   ViewerTest::CurrentView()->Redraw();
5291
5292   return 0;
5293 }
5294
5295 //==============================================================================
5296 //function : VTile
5297 //purpose  :
5298 //==============================================================================
5299 static int VTile (Draw_Interpretor& theDI,
5300                   Standard_Integer  theArgNb,
5301                   const char**      theArgVec)
5302 {
5303   Handle(V3d_View) aView = ViewerTest::CurrentView();
5304   if (aView.IsNull())
5305   {
5306     std::cerr << "Error: no active viewer.\n";
5307     return 1;
5308   }
5309
5310   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5311   if (theArgNb < 2)
5312   {
5313     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5314           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5315           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5316     return 0;
5317   }
5318
5319   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5320   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5321   {
5322     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5323     anArg.LowerCase();
5324     if (anArg == "-lowerleft"
5325      || anArg == "-upperleft")
5326     {
5327       if (anArgIter + 3 < theArgNb)
5328       {
5329         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5330         return 1;
5331       }
5332       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5333       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5334       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5335     }
5336     else if (anArg == "-total"
5337           || anArg == "-totalsize"
5338           || anArg == "-viewsize")
5339     {
5340       if (anArgIter + 3 < theArgNb)
5341       {
5342         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5343         return 1;
5344       }
5345       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5346       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5347       if (aTile.TotalSize.x() < 1
5348        || aTile.TotalSize.y() < 1)
5349       {
5350         std::cerr << "Error: total size is incorrect.\n";
5351         return 1;
5352       }
5353     }
5354     else if (anArg == "-tilesize")
5355     {
5356       if (anArgIter + 3 < theArgNb)
5357       {
5358         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5359         return 1;
5360       }
5361
5362       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5363       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5364       if (aTile.TileSize.x() < 1
5365        || aTile.TileSize.y() < 1)
5366       {
5367         std::cerr << "Error: tile size is incorrect.\n";
5368         return 1;
5369       }
5370     }
5371     else if (anArg == "-unset")
5372     {
5373       aView->Camera()->SetTile (Graphic3d_CameraTile());
5374       aView->Redraw();
5375       return 0;
5376     }
5377   }
5378
5379   if (aTile.TileSize.x() < 1
5380    || aTile.TileSize.y() < 1)
5381   {
5382     std::cerr << "Error: tile size is undefined.\n";
5383     return 1;
5384   }
5385   else if (aTile.TotalSize.x() < 1
5386         || aTile.TotalSize.y() < 1)
5387   {
5388     std::cerr << "Error: total size is undefined.\n";
5389     return 1;
5390   }
5391
5392   aView->Camera()->SetTile (aTile);
5393   aView->Redraw();
5394   return 0;
5395 }
5396
5397 //! Format ZLayer ID.
5398 inline const char* formZLayerId (const Standard_Integer theLayerId)
5399 {
5400   switch (theLayerId)
5401   {
5402     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5403     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5404     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5405     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5406     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5407     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5408   }
5409   return "";
5410 }
5411
5412 //! Print the ZLayer information.
5413 inline void printZLayerInfo (Draw_Interpretor& theDI,
5414                              const Graphic3d_ZLayerSettings& theLayer)
5415 {
5416   if (!theLayer.Name().IsEmpty())
5417   {
5418     theDI << "  Name: " << theLayer.Name() << "\n";
5419   }
5420   if (theLayer.IsImmediate())
5421   {
5422     theDI << "  Immediate: TRUE\n";
5423   }
5424   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5425   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5426   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5427   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5428   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5429   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5430   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5431   {
5432     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5433   }
5434 }
5435
5436 //==============================================================================
5437 //function : VZLayer
5438 //purpose  : Test z layer operations for v3d viewer
5439 //==============================================================================
5440 static int VZLayer (Draw_Interpretor& theDI,
5441                     Standard_Integer  theArgNb,
5442                     const char**      theArgVec)
5443 {
5444   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5445   if (aContextAIS.IsNull())
5446   {
5447     std::cout << "No active viewer!\n";
5448     return 1;
5449   }
5450
5451   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5452   if (theArgNb < 2)
5453   {
5454     TColStd_SequenceOfInteger aLayers;
5455     aViewer->GetAllZLayers (aLayers);
5456     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5457     {
5458       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5459       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5460       printZLayerInfo (theDI, aSettings);
5461     }
5462     return 1;
5463   }
5464
5465   Standard_Integer anArgIter = 1;
5466   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5467   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5468   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5469   {
5470     ++anArgIter;
5471   }
5472
5473   {
5474     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5475     if (aFirstArg.IsIntegerValue())
5476     {
5477       ++anArgIter;
5478       aLayerId = aFirstArg.IntegerValue();
5479     }
5480     else
5481     {
5482       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5483       {
5484         ++anArgIter;
5485       }
5486     }
5487   }
5488
5489   Graphic3d_ZLayerId anOtherLayerId = Graphic3d_ZLayerId_UNKNOWN;
5490   for (; anArgIter < theArgNb; ++anArgIter)
5491   {
5492     // perform operation
5493     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5494     anArg.LowerCase();
5495     if (anUpdateTool.parseRedrawMode (anArg))
5496     {
5497       //
5498     }
5499     else if (anArg == "-add"
5500           || anArg == "add")
5501     {
5502       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5503       if (!aViewer->AddZLayer (aLayerId))
5504       {
5505         std::cout << "Error: can not add a new z layer!\n";
5506         return 0;
5507       }
5508
5509       theDI << aLayerId;
5510     }
5511     else if (anArg == "-insertbefore"
5512           && anArgIter + 1 < theArgNb
5513           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5514     {
5515       ++anArgIter;
5516       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5517       if (!aViewer->InsertLayerBefore (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5518       {
5519         std::cout << "Error: can not add a new z layer!\n";
5520         return 0;
5521       }
5522
5523       theDI << aLayerId;
5524     }
5525     else if (anArg == "-insertafter"
5526           && anArgIter + 1 < theArgNb
5527           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5528     {
5529       ++anArgIter;
5530       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5531       if (!aViewer->InsertLayerAfter (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5532       {
5533         std::cout << "Error: can not add a new z layer!\n";
5534         return 0;
5535       }
5536
5537       theDI << aLayerId;
5538     }
5539     else if (anArg == "-del"
5540           || anArg == "-delete"
5541           || anArg == "del")
5542     {
5543       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5544       {
5545         if (++anArgIter >= theArgNb)
5546         {
5547           std::cout << "Syntax error: id of z layer to remove is missing\n";
5548           return 1;
5549         }
5550
5551         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5552       }
5553
5554       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5555        || aLayerId == Graphic3d_ZLayerId_Default
5556        || aLayerId == Graphic3d_ZLayerId_Top
5557        || aLayerId == Graphic3d_ZLayerId_Topmost
5558        || aLayerId == Graphic3d_ZLayerId_TopOSD
5559        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5560       {
5561         std::cout << "Syntax error: standard Z layer can not be removed\n";
5562         return 1;
5563       }
5564
5565       // move all object displayed in removing layer to default layer
5566       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5567            anObjIter.More(); anObjIter.Next())
5568       {
5569         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5570         if (aPrs.IsNull()
5571          || aPrs->ZLayer() != aLayerId)
5572         {
5573           continue;
5574         }
5575         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5576       }
5577
5578       if (!aViewer->RemoveZLayer (aLayerId))
5579       {
5580         std::cout << "Z layer can not be removed!\n";
5581       }
5582       else
5583       {
5584         theDI << aLayerId << " ";
5585       }
5586     }
5587     else if (anArg == "-get"
5588           || anArg == "get")
5589     {
5590       TColStd_SequenceOfInteger aLayers;
5591       aViewer->GetAllZLayers (aLayers);
5592       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5593       {
5594         theDI << aLayeriter.Value() << " ";
5595       }
5596
5597       theDI << "\n";
5598     }
5599     else if (anArg == "-name")
5600     {
5601       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5602       {
5603         std::cout << "Syntax error: id of Z layer is missing\n";
5604         return 1;
5605       }
5606
5607       if (++anArgIter >= theArgNb)
5608       {
5609         std::cout << "Syntax error: name is missing\n";
5610         return 1;
5611       }
5612
5613       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5614       aSettings.SetName (theArgVec[anArgIter]);
5615       aViewer->SetZLayerSettings (aLayerId, aSettings);
5616     }
5617     else if (anArg == "-origin")
5618     {
5619       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5620       {
5621         std::cout << "Syntax error: id of Z layer is missing\n";
5622         return 1;
5623       }
5624
5625       if (anArgIter + 2 >= theArgNb)
5626       {
5627         std::cout << "Syntax error: origin coordinates are missing\n";
5628         return 1;
5629       }
5630
5631       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5632       gp_XYZ anOrigin;
5633       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5634       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5635       anOrigin.SetZ (0.0);
5636       if (anArgIter + 3 < theArgNb)
5637       {
5638         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5639         anArgIter += 3;
5640       }
5641       else
5642       {
5643         anArgIter += 2;
5644       }
5645       aSettings.SetOrigin (anOrigin);
5646       aViewer->SetZLayerSettings (aLayerId, aSettings);
5647     }
5648     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5649           && anArgIter + 1 < theArgNb
5650           && (anArg == "-cullingdistance"
5651            || anArg == "-cullingdist"
5652            || anArg == "-culldistance"
5653            || anArg == "-culldist"
5654            || anArg == "-distcull"
5655            || anArg == "-distculling"
5656            || anArg == "-distanceculling"))
5657     {
5658       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5659       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5660       aSettings.SetCullingDistance (aDist);
5661       aViewer->SetZLayerSettings (aLayerId, aSettings);
5662     }
5663     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5664           && anArgIter + 1 < theArgNb
5665           && (anArg == "-cullingsize"
5666            || anArg == "-cullsize"
5667            || anArg == "-sizecull"
5668            || anArg == "-sizeculling"))
5669     {
5670       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5671       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5672       aSettings.SetCullingSize (aSize);
5673       aViewer->SetZLayerSettings (aLayerId, aSettings);
5674     }
5675     else if (anArg == "-settings"
5676           || anArg == "settings")
5677     {
5678       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5679       {
5680         if (++anArgIter >= theArgNb)
5681         {
5682           std::cout << "Syntax error: id of Z layer is missing\n";
5683           return 1;
5684         }
5685
5686         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5687       }
5688
5689       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5690       printZLayerInfo (theDI, aSettings);
5691     }
5692     else if (anArg == "-enable"
5693           || anArg == "enable"
5694           || anArg == "-disable"
5695           || anArg == "disable")
5696     {
5697       const Standard_Boolean toEnable = anArg == "-enable"
5698                                      || anArg == "enable";
5699       if (++anArgIter >= theArgNb)
5700       {
5701         std::cout << "Syntax error: option name is missing\n";
5702         return 1;
5703       }
5704
5705       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5706       aSubOp.LowerCase();
5707       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5708       {
5709         if (++anArgIter >= theArgNb)
5710         {
5711           std::cout << "Syntax error: id of Z layer is missing\n";
5712           return 1;
5713         }
5714
5715         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5716       }
5717
5718       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5719       if (aSubOp == "depthtest"
5720        || aSubOp == "test")
5721       {
5722         aSettings.SetEnableDepthTest (toEnable);
5723       }
5724       else if (aSubOp == "depthwrite"
5725             || aSubOp == "write")
5726       {
5727         aSettings.SetEnableDepthWrite (toEnable);
5728       }
5729       else if (aSubOp == "depthclear"
5730             || aSubOp == "clear")
5731       {
5732         aSettings.SetClearDepth (toEnable);
5733       }
5734       else if (aSubOp == "depthoffset"
5735             || aSubOp == "offset")
5736       {
5737         Graphic3d_PolygonOffset aParams;
5738         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5739         if (toEnable)
5740         {
5741           if (anArgIter + 2 >= theArgNb)
5742           {
5743             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5744             return 1;
5745           }
5746
5747           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5748           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5749         }
5750         aSettings.SetPolygonOffset (aParams);
5751       }
5752       else if (aSubOp == "positiveoffset"
5753             || aSubOp == "poffset")
5754       {
5755         if (toEnable)
5756         {
5757           aSettings.SetDepthOffsetPositive();
5758         }
5759         else
5760         {
5761           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5762         }
5763       }
5764       else if (aSubOp == "negativeoffset"
5765             || aSubOp == "noffset")
5766       {
5767         if (toEnable)
5768         {
5769           aSettings.SetDepthOffsetNegative();
5770         }
5771         else
5772         {
5773           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5774         }
5775       }
5776       else if (aSubOp == "textureenv")
5777       {
5778         aSettings.SetEnvironmentTexture (toEnable);
5779       }
5780       else if (aSubOp == "raytracing")
5781       {
5782         aSettings.SetRaytracable (toEnable);
5783       }
5784
5785       aViewer->SetZLayerSettings (aLayerId, aSettings);
5786     }
5787     else
5788     {
5789       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5790       return 1;
5791     }
5792   }
5793
5794   return 0;
5795 }
5796
5797 // The interactive presentation of 2d layer item
5798 // for "vlayerline" command it provides a presentation of
5799 // line with user-defined linewidth, linetype and transparency.
5800 class V3d_LineItem : public AIS_InteractiveObject
5801 {
5802 public:
5803   // CASCADE RTTI
5804   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5805
5806   // constructor
5807   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5808                                Standard_Real X2, Standard_Real Y2,
5809                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5810                                Standard_Real theWidth    = 0.5,
5811                                Standard_Real theTransp   = 1.0);
5812
5813   private:
5814
5815   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5816                 const Handle(Prs3d_Presentation)& thePresentation,
5817                 const Standard_Integer theMode) Standard_OVERRIDE;
5818
5819   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5820                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5821   {}
5822
5823 private:
5824
5825   Standard_Real       myX1, myY1, myX2, myY2;
5826   Aspect_TypeOfLine   myType;
5827   Standard_Real       myWidth;
5828 };
5829
5830 // default constructor for line item
5831 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5832                            Standard_Real X2, Standard_Real Y2,
5833                            Aspect_TypeOfLine theType,
5834                            Standard_Real theWidth,
5835                            Standard_Real theTransp) :
5836   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5837   myType(theType), myWidth(theWidth)
5838 {
5839   SetTransparency (1-theTransp);
5840 }
5841
5842 // render line
5843 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5844                             const Handle(Prs3d_Presentation)& thePresentation,
5845                             const Standard_Integer /*theMode*/)
5846 {
5847   thePresentation->Clear();
5848   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5849   Standard_Integer aWidth, aHeight;
5850   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5851   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5852   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5853   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5854   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5855   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5856   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5857   aGroup->AddPrimitiveArray (aPrim);
5858 }
5859
5860 //=============================================================================
5861 //function : VLayerLine
5862 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5863 //         : linewidth, transparency coefficient
5864 //============================================================================
5865 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5866 {
5867   // get the active view
5868   Handle(V3d_View) aView = ViewerTest::CurrentView();
5869   if (aView.IsNull())
5870   {
5871     di << "Call vinit before!\n";
5872     return 1;
5873   }
5874   else if (argc < 5)
5875   {
5876     di << "Use: " << argv[0];
5877     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5878     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5879     di << "              0 - solid  \n";
5880     di << "              1 - dashed \n";
5881     di << "              2 - dot    \n";
5882     di << "              3 - dashdot\n";
5883     di << " transparency : { 0.0 - 1.0 } \n";
5884     di << "                  0.0 - transparent\n";
5885     di << "                  1.0 - visible    \n";
5886     return 1;
5887   }
5888
5889   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5890   // get the input params
5891   Standard_Real X1 = Draw::Atof(argv[1]);
5892   Standard_Real Y1 = Draw::Atof(argv[2]);
5893   Standard_Real X2 = Draw::Atof(argv[3]);
5894   Standard_Real Y2 = Draw::Atof(argv[4]);
5895
5896   Standard_Real aWidth = 0.5;
5897   Standard_Real aTransparency = 1.0;
5898
5899   // has width
5900   if (argc > 5)
5901     aWidth = Draw::Atof(argv[5]);
5902
5903   // select appropriate line type
5904   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5905   if (argc > 6
5906   && !ViewerTest::ParseLineType (argv[6], aLineType))
5907   {
5908     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5909     return 1;
5910   }
5911
5912   // has transparency
5913   if (argc > 7)
5914   {
5915     aTransparency = Draw::Atof(argv[7]);
5916     if (aTransparency < 0 || aTransparency > 1.0)
5917       aTransparency = 1.0;
5918   }
5919
5920   static Handle (V3d_LineItem) aLine;
5921   if (!aLine.IsNull())
5922   {
5923     aContext->Erase (aLine, Standard_False);
5924   }
5925   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5926                             aLineType, aWidth,
5927                             aTransparency);
5928
5929   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5930   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5931   aLine->SetToUpdate();
5932   aContext->Display (aLine, Standard_True);
5933
5934   return 0;
5935 }
5936
5937
5938 //==============================================================================
5939 //function : VGrid
5940 //purpose  :
5941 //==============================================================================
5942
5943 static int VGrid (Draw_Interpretor& /*theDI*/,
5944                   Standard_Integer  theArgNb,
5945                   const char**      theArgVec)
5946 {
5947   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5948   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5949   if (aView.IsNull() || aViewer.IsNull())
5950   {
5951     std::cerr << "Error: no active view\n";
5952     return 1;
5953   }
5954
5955   Aspect_GridType     aType = aViewer->GridType();
5956   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5957   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5958   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5959   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5960   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5961   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5962   {
5963     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5964     anArg.LowerCase();
5965     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5966     {
5967       continue;
5968     }
5969     else if (anArgIter + 1 < theArgNb
5970           && anArg == "-type")
5971     {
5972       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5973       anArgNext.LowerCase();
5974       if (anArgNext == "r"
5975        || anArgNext == "rect"
5976        || anArgNext == "rectangular")
5977       {
5978         aType = Aspect_GT_Rectangular;
5979       }
5980       else if (anArgNext == "c"
5981             || anArgNext == "circ"
5982             || anArgNext == "circular")
5983       {
5984         aType = Aspect_GT_Circular;
5985       }
5986       else
5987       {
5988         std::cout << "Syntax error at '" << anArgNext << "'\n";
5989         return 1;
5990       }
5991     }
5992     else if (anArgIter + 1 < theArgNb
5993           && anArg == "-mode")
5994     {
5995       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5996       anArgNext.LowerCase();
5997       if (anArgNext == "l"
5998        || anArgNext == "line"
5999        || anArgNext == "lines")
6000       {
6001         aMode = Aspect_GDM_Lines;
6002       }
6003       else if (anArgNext == "p"
6004             || anArgNext == "point"
6005             || anArgNext == "points")
6006       {
6007         aMode = Aspect_GDM_Points;
6008       }
6009       else
6010       {
6011         std::cout << "Syntax error at '" << anArgNext << "'\n";
6012         return 1;
6013       }
6014     }
6015     else if (anArgIter + 2 < theArgNb
6016           && (anArg == "-origin"
6017            || anArg == "-orig"))
6018     {
6019       hasOrigin = true;
6020       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6021                               Draw::Atof (theArgVec[anArgIter + 2]));
6022       anArgIter += 2;
6023     }
6024     else if (anArgIter + 2 < theArgNb
6025           && anArg == "-step")
6026     {
6027       hasStep = true;
6028       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6029                             Draw::Atof (theArgVec[anArgIter + 2]));
6030       if (aNewStepXY.x() <= 0.0
6031        || aNewStepXY.y() <= 0.0)
6032       {
6033         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6034         return 1;
6035       }
6036       anArgIter += 2;
6037     }
6038     else if (anArgIter + 1 < theArgNb
6039           && (anArg == "-angle"
6040            || anArg == "-rotangle"
6041            || anArg == "-rotationangle"))
6042     {
6043       hasRotAngle = true;
6044       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
6045     }
6046     else if (anArgIter + 1 < theArgNb
6047           && (anArg == "-zoffset"
6048            || anArg == "-dz"))
6049     {
6050       hasZOffset = true;
6051       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
6052     }
6053     else if (anArgIter + 1 < theArgNb
6054           && anArg == "-radius")
6055     {
6056       hasSize = true;
6057       ++anArgIter;
6058       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
6059       if (aNewStepXY.x() <= 0.0)
6060       {
6061         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
6062         return 1;
6063       }
6064     }
6065     else if (anArgIter + 2 < theArgNb
6066           && anArg == "-size")
6067     {
6068       hasSize = true;
6069       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
6070                             Draw::Atof (theArgVec[anArgIter + 2]));
6071       if (aNewStepXY.x() <= 0.0
6072        || aNewStepXY.y() <= 0.0)
6073       {
6074         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
6075         return 1;
6076       }
6077       anArgIter += 2;
6078     }
6079     else if (anArg == "r"
6080           || anArg == "rect"
6081           || anArg == "rectangular")
6082     {
6083       aType = Aspect_GT_Rectangular;
6084     }
6085     else if (anArg == "c"
6086           || anArg == "circ"
6087           || anArg == "circular")
6088     {
6089       aType = Aspect_GT_Circular;
6090     }
6091     else if (anArg == "l"
6092           || anArg == "line"
6093           || anArg == "lines")
6094     {
6095       aMode = Aspect_GDM_Lines;
6096     }
6097     else if (anArg == "p"
6098           || anArg == "point"
6099           || anArg == "points")
6100     {
6101       aMode = Aspect_GDM_Points;
6102     }
6103     else if (anArgIter + 1 >= theArgNb
6104           && anArg == "off")
6105     {
6106       aViewer->DeactivateGrid();
6107       return 0;
6108     }
6109     else
6110     {
6111       std::cout << "Syntax error at '" << anArg << "'\n";
6112       return 1;
6113     }
6114   }
6115
6116   if (aType == Aspect_GT_Rectangular)
6117   {
6118     Graphic3d_Vec2d anOrigXY, aStepXY;
6119     Standard_Real aRotAngle = 0.0;
6120     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6121     if (hasOrigin)
6122     {
6123       anOrigXY = aNewOriginXY;
6124     }
6125     if (hasStep)
6126     {
6127       aStepXY = aNewStepXY;
6128     }
6129     if (hasRotAngle)
6130     {
6131       aRotAngle = aNewRotAngle;
6132     }
6133     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
6134     if (hasSize || hasZOffset)
6135     {
6136       Graphic3d_Vec3d aSize;
6137       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6138       if (hasSize)
6139       {
6140         aSize.x() = aNewSizeXY.x();
6141         aSize.y() = aNewSizeXY.y();
6142       }
6143       if (hasZOffset)
6144       {
6145         aSize.z() = aNewZOffset;
6146       }
6147       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
6148     }
6149   }
6150   else if (aType == Aspect_GT_Circular)
6151   {
6152     Graphic3d_Vec2d anOrigXY;
6153     Standard_Real aRadiusStep;
6154     Standard_Integer aDivisionNumber;
6155     Standard_Real aRotAngle = 0.0;
6156     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6157     if (hasOrigin)
6158     {
6159       anOrigXY = aNewOriginXY;
6160     }
6161     if (hasStep)
6162     {
6163       aRadiusStep     = aNewStepXY[0];
6164       aDivisionNumber = (int )aNewStepXY[1];
6165       if (aDivisionNumber < 1)
6166       {
6167         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6168         return 1;
6169       }
6170     }
6171     if (hasRotAngle)
6172     {
6173       aRotAngle = aNewRotAngle;
6174     }
6175
6176     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6177     if (hasSize || hasZOffset)
6178     {
6179       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6180       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6181       if (hasSize)
6182       {
6183         aRadius = aNewSizeXY.x();
6184         if (aNewSizeXY.y() != 0.0)
6185         {
6186           std::cout << "Syntax error: circular size should be specified as radius\n";
6187           return 1;
6188         }
6189       }
6190       if (hasZOffset)
6191       {
6192         aZOffset = aNewZOffset;
6193       }
6194       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6195     }
6196   }
6197   aViewer->ActivateGrid (aType, aMode);
6198   return 0;
6199 }
6200
6201 //==============================================================================
6202 //function : VPriviledgedPlane
6203 //purpose  :
6204 //==============================================================================
6205
6206 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6207                               Standard_Integer  theArgNb,
6208                               const char**      theArgVec)
6209 {
6210   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6211   {
6212     std::cerr << "Error: wrong number of arguments! See usage:\n";
6213     theDI.PrintHelp (theArgVec[0]);
6214     return 1;
6215   }
6216
6217   // get the active viewer
6218   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6219   if (aViewer.IsNull())
6220   {
6221     std::cerr << "Error: no active viewer. Please call vinit.\n";
6222     return 1;
6223   }
6224
6225   if (theArgNb == 1)
6226   {
6227     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6228     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6229     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6230     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6231     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6232           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6233           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6234     return 0;
6235   }
6236
6237   Standard_Integer anArgIdx = 1;
6238   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6239   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6240   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6241   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6242   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6243   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6244
6245   gp_Ax3 aPriviledgedPlane;
6246   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6247   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6248   if (theArgNb > 7)
6249   {
6250     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6251     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6252     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6253     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6254     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6255   }
6256   else
6257   {
6258     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6259   }
6260
6261   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6262
6263   return 0;
6264 }
6265
6266 //==============================================================================
6267 //function : VConvert
6268 //purpose  :
6269 //==============================================================================
6270
6271 static int VConvert (Draw_Interpretor& theDI,
6272                      Standard_Integer  theArgNb,
6273                      const char**      theArgVec)
6274 {
6275   // get the active view
6276   Handle(V3d_View) aView = ViewerTest::CurrentView();
6277   if (aView.IsNull())
6278   {
6279     std::cerr << "Error: no active view. Please call vinit.\n";
6280     return 1;
6281   }
6282
6283   enum { Model, Ray, View, Window, Grid } aMode = Model;
6284
6285   // access coordinate arguments
6286   TColStd_SequenceOfReal aCoord;
6287   Standard_Integer anArgIdx = 1;
6288   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6289   {
6290     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6291     if (!anArg.IsRealValue())
6292     {
6293       break;
6294     }
6295     aCoord.Append (anArg.RealValue());
6296   }
6297
6298   // non-numeric argument too early
6299   if (aCoord.IsEmpty())
6300   {
6301     std::cerr << "Error: wrong number of arguments! See usage:\n";
6302     theDI.PrintHelp (theArgVec[0]);
6303     return 1;
6304   }
6305
6306   // collect all other arguments and options
6307   for (; anArgIdx < theArgNb; ++anArgIdx)
6308   {
6309     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6310     anArg.LowerCase();
6311     if      (anArg == "window") aMode = Window;
6312     else if (anArg == "view")   aMode = View;
6313     else if (anArg == "grid")   aMode = Grid;
6314     else if (anArg == "ray")    aMode = Ray;
6315     else
6316     {
6317       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6318       theDI.PrintHelp (theArgVec[0]);
6319       return 1;
6320     }
6321   }
6322
6323   // complete input checks
6324   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6325       (aCoord.Length() == 2 && theArgNb > 4) ||
6326       (aCoord.Length() == 3 && theArgNb > 5))
6327   {
6328     std::cerr << "Error: wrong number of arguments! See usage:\n";
6329     theDI.PrintHelp (theArgVec[0]);
6330     return 1;
6331   }
6332
6333   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6334   Standard_Integer aXYp[2] = {0, 0};
6335
6336   // convert one-dimensional coordinate
6337   if (aCoord.Length() == 1)
6338   {
6339     switch (aMode)
6340     {
6341       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6342       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6343       default:
6344         std::cerr << "Error: wrong arguments! See usage:\n";
6345         theDI.PrintHelp (theArgVec[0]);
6346         return 1;
6347     }
6348   }
6349
6350   // convert 2D coordinates from projection or view reference space
6351   if (aCoord.Length() == 2)
6352   {
6353     switch (aMode)
6354     {
6355       case Model :
6356         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6357         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6358         return 0;
6359
6360       case View :
6361         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6362         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6363         return 0;
6364
6365       case Window :
6366         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6367         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6368         return 0;
6369
6370       case Grid :
6371         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6372         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6373         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6374         return 0;
6375
6376       case Ray :
6377         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6378                                 (Standard_Integer) aCoord (2),
6379                                 aXYZ[0], aXYZ[1], aXYZ[2],
6380                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6381         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6382         return 0;
6383
6384       default:
6385         std::cerr << "Error: wrong arguments! See usage:\n";
6386         theDI.PrintHelp (theArgVec[0]);
6387         return 1;
6388     }
6389   }
6390
6391   // convert 3D coordinates from view reference space
6392   else if (aCoord.Length() == 3)
6393   {
6394     switch (aMode)
6395     {
6396       case Window :
6397         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6398         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6399         return 0;
6400
6401       case Grid :
6402         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6403         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6404         return 0;
6405
6406       default:
6407         std::cerr << "Error: wrong arguments! See usage:\n";
6408         theDI.PrintHelp (theArgVec[0]);
6409         return 1;
6410     }
6411   }
6412
6413   return 0;
6414 }
6415
6416 //==============================================================================
6417 //function : VFps
6418 //purpose  :
6419 //==============================================================================
6420
6421 static int VFps (Draw_Interpretor& theDI,
6422                  Standard_Integer  theArgNb,
6423                  const char**      theArgVec)
6424 {
6425   // get the active view
6426   Handle(V3d_View) aView = ViewerTest::CurrentView();
6427   if (aView.IsNull())
6428   {
6429     std::cerr << "No active view. Please call vinit.\n";
6430     return 1;
6431   }
6432
6433   Standard_Integer aFramesNb = -1;
6434   Standard_Real aDuration = -1.0;
6435   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6436   {
6437     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6438     anArg.LowerCase();
6439     if (aDuration < 0.0
6440      && anArgIter + 1 < theArgNb
6441      && (anArg == "-duration"
6442       || anArg == "-dur"
6443       || anArg == "-time"))
6444     {
6445       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6446     }
6447     else if (aFramesNb < 0
6448           && anArg.IsIntegerValue())
6449     {
6450       aFramesNb = anArg.IntegerValue();
6451       if (aFramesNb <= 0)
6452       {
6453         std::cerr << "Syntax error at '" << anArg << "'\n";
6454         return 1;
6455       }
6456     }
6457     else
6458     {
6459       std::cerr << "Syntax error at '" << anArg << "'\n";
6460       return 1;
6461     }
6462   }
6463   if (aFramesNb < 0 && aDuration < 0.0)
6464   {
6465     aFramesNb = 100;
6466   }
6467
6468   // the time is meaningless for first call
6469   // due to async OpenGl rendering
6470   aView->Redraw();
6471
6472   // redraw view in loop to estimate average values
6473   OSD_Timer aTimer;
6474   aTimer.Start();
6475   Standard_Integer aFrameIter = 1;
6476   for (;; ++aFrameIter)
6477   {
6478     aView->Redraw();
6479     if ((aFramesNb > 0
6480       && aFrameIter >= aFramesNb)
6481      || (aDuration > 0.0
6482       && aTimer.ElapsedTime() >= aDuration))
6483     {
6484       break;
6485     }
6486   }
6487   aTimer.Stop();
6488   Standard_Real aCpu;
6489   const Standard_Real aTime = aTimer.ElapsedTime();
6490   aTimer.OSD_Chronometer::Show (aCpu);
6491
6492   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6493   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6494
6495   // return statistics
6496   theDI << "FPS: " << aFpsAver << "\n"
6497         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6498
6499   // compute additional statistics in ray-tracing mode
6500   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6501   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6502   {
6503     Graphic3d_Vec2i aWinSize (0, 0);
6504     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6505
6506     // 1 shadow ray and 1 secondary ray pew each bounce
6507     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6508     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6509   }
6510
6511   return 0;
6512 }
6513
6514 //! Auxiliary function for parsing glsl dump level argument.
6515 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6516                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6517 {
6518   TCollection_AsciiString aTypeStr (theArg);
6519   aTypeStr.LowerCase();
6520   if (aTypeStr == "off"
6521    || aTypeStr == "0")
6522   {
6523     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6524   }
6525   else if (aTypeStr == "short")
6526   {
6527     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6528   }
6529   else if (aTypeStr == "full"
6530         || aTypeStr == "1")
6531   {
6532     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6533   }
6534   else
6535   {
6536     return Standard_False;
6537   }
6538   return Standard_True;
6539 }
6540
6541 //==============================================================================
6542 //function : VGlDebug
6543 //purpose  :
6544 //==============================================================================
6545
6546 static int VGlDebug (Draw_Interpretor& theDI,
6547                      Standard_Integer  theArgNb,
6548                      const char**      theArgVec)
6549 {
6550   Handle(OpenGl_GraphicDriver) aDriver;
6551   Handle(V3d_View) aView = ViewerTest::CurrentView();
6552   if (!aView.IsNull())
6553   {
6554     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6555   }
6556   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6557   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6558
6559   if (theArgNb < 2)
6560   {
6561     TCollection_AsciiString aDebActive, aSyncActive;
6562     if (aCaps == NULL)
6563     {
6564       aCaps = aDefCaps;
6565     }
6566     else
6567     {
6568       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6569                                                                   "GL_ARB_debug_output");
6570       aDebActive = isActive ? " (active)" : " (inactive)";
6571       if (isActive)
6572       {
6573         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6574         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6575       }
6576     }
6577
6578     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6579       + "glslSourceCode: "
6580       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6581          ? "Off"
6582          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6583           ? "Short"
6584           : "Full")
6585       + "\n";
6586     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6587           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6588           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6589           << aGlslCodeDebugStatus
6590           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6591     return 0;
6592   }
6593
6594   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6595   {
6596     Standard_CString        anArg     = theArgVec[anArgIter];
6597     TCollection_AsciiString anArgCase (anArg);
6598     anArgCase.LowerCase();
6599     Standard_Boolean toEnableDebug = Standard_True;
6600     if (anArgCase == "-glsl"
6601      || anArgCase == "-glslwarn"
6602      || anArgCase == "-glslwarns"
6603      || anArgCase == "-glslwarnings")
6604     {
6605       Standard_Boolean toShowWarns = Standard_True;
6606       if (++anArgIter < theArgNb
6607       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6608       {
6609         --anArgIter;
6610       }
6611       aDefCaps->glslWarnings = toShowWarns;
6612       if (aCaps != NULL)
6613       {
6614         aCaps->glslWarnings = toShowWarns;
6615       }
6616     }
6617     else if (anArgCase == "-extra"
6618           || anArgCase == "-extramsg"
6619           || anArgCase == "-extramessages")
6620     {
6621       Standard_Boolean toShow = Standard_True;
6622       if (++anArgIter < theArgNb
6623       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6624       {
6625         --anArgIter;
6626       }
6627       aDefCaps->suppressExtraMsg = !toShow;
6628       if (aCaps != NULL)
6629       {
6630         aCaps->suppressExtraMsg = !toShow;
6631       }
6632     }
6633     else if (anArgCase == "-noextra"
6634           || anArgCase == "-noextramsg"
6635           || anArgCase == "-noextramessages")
6636     {
6637       Standard_Boolean toSuppress = Standard_True;
6638       if (++anArgIter < theArgNb
6639       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6640       {
6641         --anArgIter;
6642       }
6643       aDefCaps->suppressExtraMsg = toSuppress;
6644       if (aCaps != NULL)
6645       {
6646         aCaps->suppressExtraMsg = toSuppress;
6647       }
6648     }
6649     else if (anArgCase == "-sync")
6650     {
6651       Standard_Boolean toSync = Standard_True;
6652       if (++anArgIter < theArgNb
6653       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6654       {
6655         --anArgIter;
6656       }
6657       aDefCaps->contextSyncDebug = toSync;
6658       if (toSync)
6659       {
6660         aDefCaps->contextDebug = Standard_True;
6661       }
6662     }
6663     else if (anArgCase == "-glslsourcecode"
6664           || anArgCase == "-glslcode")
6665     {
6666       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6667       if (++anArgIter < theArgNb
6668       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6669       {
6670         --anArgIter;
6671       }
6672       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6673       if (aCaps != NULL)
6674       {
6675         aCaps->glslDumpLevel = aGslsDumpLevel;
6676       }
6677     }
6678     else if (anArgCase == "-debug")
6679     {
6680       if (++anArgIter < theArgNb
6681       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6682       {
6683         --anArgIter;
6684       }
6685       aDefCaps->contextDebug = toEnableDebug;
6686     }
6687     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6688           && (anArgIter + 1 == theArgNb))
6689     {
6690       // simple alias to turn on almost everything
6691       aDefCaps->contextDebug     = toEnableDebug;
6692       aDefCaps->contextSyncDebug = toEnableDebug;
6693       aDefCaps->glslWarnings     = toEnableDebug;
6694       if (!toEnableDebug)
6695       {
6696         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6697       }
6698       aDefCaps->suppressExtraMsg = !toEnableDebug;
6699       if (aCaps != NULL)
6700       {
6701         aCaps->contextDebug     = toEnableDebug;
6702         aCaps->contextSyncDebug = toEnableDebug;
6703         aCaps->glslWarnings     = toEnableDebug;
6704         if (!toEnableDebug)
6705         {
6706           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6707         }
6708         aCaps->suppressExtraMsg = !toEnableDebug;
6709       }
6710     }
6711     else
6712     {
6713       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6714       return 1;
6715     }
6716   }
6717
6718   return 0;
6719 }
6720
6721 //==============================================================================
6722 //function : VVbo
6723 //purpose  :
6724 //==============================================================================
6725
6726 static int VVbo (Draw_Interpretor& theDI,
6727                  Standard_Integer  theArgNb,
6728                  const char**      theArgVec)
6729 {
6730   const Standard_Boolean toSet    = (theArgNb > 1);
6731   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6732   if (toSet)
6733   {
6734     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6735   }
6736
6737   // get the context
6738   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6739   if (aContextAIS.IsNull())
6740   {
6741     if (!toSet)
6742     {
6743       std::cerr << "No active view!\n";
6744     }
6745     return 1;
6746   }
6747   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6748   if (!aDriver.IsNull())
6749   {
6750     if (!toSet)
6751     {
6752       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6753     }
6754     else
6755     {
6756       aDriver->ChangeOptions().vboDisable = toUseVbo;
6757     }
6758   }
6759
6760   return 0;
6761 }
6762
6763 //==============================================================================
6764 //function : VCaps
6765 //purpose  :
6766 //==============================================================================
6767
6768 static int VCaps (Draw_Interpretor& theDI,
6769                   Standard_Integer  theArgNb,
6770                   const char**      theArgVec)
6771 {
6772   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6773   Handle(OpenGl_GraphicDriver)   aDriver;
6774   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6775   if (!aContext.IsNull())
6776   {
6777     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6778     aCaps   = &aDriver->ChangeOptions();
6779   }
6780
6781   if (theArgNb < 2)
6782   {
6783     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6784     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6785     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6786     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6787     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6788     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6789     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6790     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6791     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6792     theDI << "NoExt:"    << (aCaps->contextNoExtensions ? "1" : "0") << "\n";
6793     theDI << "MaxVersion:" << aCaps->contextMajorVersionUpper << "." << aCaps->contextMinorVersionUpper << "\n";
6794     return 0;
6795   }
6796
6797   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6798   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6799   {
6800     Standard_CString        anArg     = theArgVec[anArgIter];
6801     TCollection_AsciiString anArgCase (anArg);
6802     anArgCase.LowerCase();
6803     if (anUpdateTool.parseRedrawMode (anArg))
6804     {
6805       continue;
6806     }
6807     else if (anArgCase == "-vsync"
6808           || anArgCase == "-swapinterval")
6809     {
6810       Standard_Boolean toEnable = Standard_True;
6811       if (++anArgIter < theArgNb
6812       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6813       {
6814         --anArgIter;
6815       }
6816       aCaps->swapInterval = toEnable;
6817     }
6818     else if (anArgCase == "-ffp")
6819     {
6820       Standard_Boolean toEnable = Standard_True;
6821       if (++anArgIter < theArgNb
6822       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6823       {
6824         --anArgIter;
6825       }
6826       aCaps->ffpEnable = toEnable;
6827     }
6828     else if (anArgCase == "-polygonmode")
6829     {
6830       Standard_Boolean toEnable = Standard_True;
6831       if (++anArgIter < theArgNb
6832       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6833       {
6834         --anArgIter;
6835       }
6836       aCaps->usePolygonMode = toEnable;
6837     }
6838     else if (anArgCase == "-vbo")
6839     {
6840       Standard_Boolean toEnable = Standard_True;
6841       if (++anArgIter < theArgNb
6842       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6843       {
6844         --anArgIter;
6845       }
6846       aCaps->vboDisable = !toEnable;
6847     }
6848     else if (anArgCase == "-sprite"
6849           || anArgCase == "-sprites")
6850     {
6851       Standard_Boolean toEnable = Standard_True;
6852       if (++anArgIter < theArgNb
6853       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6854       {
6855         --anArgIter;
6856       }
6857       aCaps->pntSpritesDisable = !toEnable;
6858     }
6859     else if (anArgCase == "-softmode")
6860     {
6861       Standard_Boolean toEnable = Standard_True;
6862       if (++anArgIter < theArgNb
6863       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6864       {
6865         --anArgIter;
6866       }
6867       aCaps->contextNoAccel = toEnable;
6868     }
6869     else if (anArgCase == "-winbuffer"
6870           || anArgCase == "-windowbuffer"
6871           || anArgCase == "-usewinbuffer"
6872           || anArgCase == "-usewindowbuffer"
6873           || anArgCase == "-usesystembuffer")
6874     {
6875       Standard_Boolean toEnable = Standard_True;
6876       if (++anArgIter < theArgNb
6877       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6878       {
6879         --anArgIter;
6880       }
6881       aCaps->useSystemBuffer = toEnable;
6882     }
6883     else if (anArgCase == "-accel"
6884           || anArgCase == "-acceleration")
6885     {
6886       Standard_Boolean toEnable = Standard_True;
6887       if (++anArgIter < theArgNb
6888       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6889       {
6890         --anArgIter;
6891       }
6892       aCaps->contextNoAccel = !toEnable;
6893     }
6894     else if (anArgCase == "-compat"
6895           || anArgCase == "-compatprofile"
6896           || anArgCase == "-compatible"
6897           || anArgCase == "-compatibleprofile")
6898     {
6899       Standard_Boolean toEnable = Standard_True;
6900       if (++anArgIter < theArgNb
6901       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6902       {
6903         --anArgIter;
6904       }
6905       aCaps->contextCompatible = toEnable;
6906       if (!aCaps->contextCompatible)
6907       {
6908         aCaps->ffpEnable = Standard_False;
6909       }
6910     }
6911     else if (anArgCase == "-core"
6912           || anArgCase == "-coreprofile")
6913     {
6914       Standard_Boolean toEnable = Standard_True;
6915       if (++anArgIter < theArgNb
6916       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6917       {
6918         --anArgIter;
6919       }
6920       aCaps->contextCompatible = !toEnable;
6921       if (!aCaps->contextCompatible)
6922       {
6923         aCaps->ffpEnable = Standard_False;
6924       }
6925     }
6926     else if (anArgCase == "-stereo"
6927           || anArgCase == "-quadbuffer")
6928     {
6929       Standard_Boolean toEnable = Standard_True;
6930       if (++anArgIter < theArgNb
6931       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6932       {
6933         --anArgIter;
6934       }
6935       aCaps->contextStereo = toEnable;
6936     }
6937     else if (anArgCase == "-noext"
6938           || anArgCase == "-noextensions"
6939           || anArgCase == "-noextension")
6940     {
6941       Standard_Boolean toDisable = Standard_True;
6942       if (++anArgIter < theArgNb
6943       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
6944       {
6945         --anArgIter;
6946       }
6947       aCaps->contextNoExtensions = toDisable;
6948     }
6949     else if (anArgCase == "-maxversion"
6950           || anArgCase == "-upperversion"
6951           || anArgCase == "-limitversion")
6952     {
6953       Standard_Integer aVer[2] = { -2, -1 };
6954       for (Standard_Integer aValIter = 0; aValIter < 2; ++aValIter)
6955       {
6956         if (anArgIter + 1 < theArgNb)
6957         {
6958           const TCollection_AsciiString aStr (theArgVec[anArgIter + 1]);
6959           if (aStr.IsIntegerValue())
6960           {
6961             aVer[aValIter] = aStr.IntegerValue();
6962             ++anArgIter;
6963           }
6964         }
6965       }
6966       if (aVer[0] < -1
6967        || aVer[1] < -1)
6968       {
6969         std::cout << "Syntax error at '" << anArgCase << "'\n";
6970         return 1;
6971       }
6972       aCaps->contextMajorVersionUpper = aVer[0];
6973       aCaps->contextMinorVersionUpper = aVer[1];
6974     }
6975     else
6976     {
6977       std::cout << "Error: unknown argument '" << anArg << "'\n";
6978       return 1;
6979     }
6980   }
6981   if (aCaps != &ViewerTest_myDefaultCaps)
6982   {
6983     ViewerTest_myDefaultCaps = *aCaps;
6984   }
6985   return 0;
6986 }
6987
6988 //==============================================================================
6989 //function : VMemGpu
6990 //purpose  :
6991 //==============================================================================
6992
6993 static int VMemGpu (Draw_Interpretor& theDI,
6994                     Standard_Integer  theArgNb,
6995                     const char**      theArgVec)
6996 {
6997   // get the context
6998   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6999   if (aContextAIS.IsNull())
7000   {
7001     std::cerr << "No active view. Please call vinit.\n";
7002     return 1;
7003   }
7004
7005   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
7006   if (aDriver.IsNull())
7007   {
7008     std::cerr << "Graphic driver not available.\n";
7009     return 1;
7010   }
7011
7012   Standard_Size aFreeBytes = 0;
7013   TCollection_AsciiString anInfo;
7014   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
7015   {
7016     std::cerr << "Information not available.\n";
7017     return 1;
7018   }
7019
7020   if (theArgNb > 1 && *theArgVec[1] == 'f')
7021   {
7022     theDI << Standard_Real (aFreeBytes);
7023   }
7024   else
7025   {
7026     theDI << anInfo;
7027   }
7028
7029   return 0;
7030 }
7031
7032 // ==============================================================================
7033 // function : VReadPixel
7034 // purpose  :
7035 // ==============================================================================
7036 static int VReadPixel (Draw_Interpretor& theDI,
7037                        Standard_Integer  theArgNb,
7038                        const char**      theArgVec)
7039 {
7040   // get the active view
7041   Handle(V3d_View) aView = ViewerTest::CurrentView();
7042   if (aView.IsNull())
7043   {
7044     std::cerr << "No active view. Please call vinit.\n";
7045     return 1;
7046   }
7047   else if (theArgNb < 3)
7048   {
7049     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
7050     return 1;
7051   }
7052
7053   Image_Format         aFormat     = Image_Format_RGBA;
7054   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
7055
7056   Standard_Integer aWidth, aHeight;
7057   aView->Window()->Size (aWidth, aHeight);
7058   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
7059   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
7060   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
7061   {
7062     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
7063     return 1;
7064   }
7065
7066   Standard_Boolean toShowName = Standard_False;
7067   Standard_Boolean toShowHls  = Standard_False;
7068   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
7069   {
7070     TCollection_AsciiString aParam (theArgVec[anIter]);
7071     aParam.LowerCase();
7072     if (aParam == "-rgb"
7073      || aParam == "rgb")
7074     {
7075       aFormat     = Image_Format_RGB;
7076       aBufferType = Graphic3d_BT_RGB;
7077     }
7078     else if (aParam == "-hls"
7079           || aParam == "hls")
7080     {
7081       aFormat     = Image_Format_RGB;
7082       aBufferType = Graphic3d_BT_RGB;
7083       toShowHls   = Standard_True;
7084     }
7085     else if (aParam == "-rgbf"
7086           || aParam == "rgbf")
7087     {
7088       aFormat     = Image_Format_RGBF;
7089       aBufferType = Graphic3d_BT_RGB;
7090     }
7091     else if (aParam == "-rgba"
7092           || aParam == "rgba")
7093     {
7094       aFormat     = Image_Format_RGBA;
7095       aBufferType = Graphic3d_BT_RGBA;
7096     }
7097     else if (aParam == "-rgbaf"
7098           || aParam == "rgbaf")
7099     {
7100       aFormat     = Image_Format_RGBAF;
7101       aBufferType = Graphic3d_BT_RGBA;
7102     }
7103     else if (aParam == "-depth"
7104           || aParam == "depth")
7105     {
7106       aFormat     = Image_Format_GrayF;
7107       aBufferType = Graphic3d_BT_Depth;
7108     }
7109     else if (aParam == "-name"
7110           || aParam == "name")
7111     {
7112       toShowName = Standard_True;
7113     }
7114     else
7115     {
7116       std::cout << "Syntax error at '" << aParam << "'\n";
7117     }
7118   }
7119
7120   Image_PixMap anImage;
7121   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
7122   {
7123     std::cerr << "Image allocation failed\n";
7124     return 1;
7125   }
7126   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
7127   {
7128     std::cerr << "Image dump failed\n";
7129     return 1;
7130   }
7131
7132   // redirect possible warning messages that could have been added by ToPixMap
7133   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
7134   // contaminate result of the command
7135   Standard_CString aWarnLog = theDI.Result();
7136   if (aWarnLog != NULL && aWarnLog[0] != '\0')
7137   {
7138     std::cout << aWarnLog << std::endl;
7139   }
7140   theDI.Reset();
7141
7142   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
7143   if (toShowName)
7144   {
7145     if (aBufferType == Graphic3d_BT_RGBA)
7146     {
7147       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
7148     }
7149     else
7150     {
7151       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
7152     }
7153   }
7154   else
7155   {
7156     switch (aBufferType)
7157     {
7158       default:
7159       case Graphic3d_BT_RGB:
7160       {
7161         if (toShowHls)
7162         {
7163           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
7164         }
7165         else
7166         {
7167           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
7168         }
7169         break;
7170       }
7171       case Graphic3d_BT_RGBA:
7172       {
7173         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
7174         break;
7175       }
7176       case Graphic3d_BT_Depth:
7177       {
7178         theDI << aColor.GetRGB().Red();
7179         break;
7180       }
7181     }
7182   }
7183
7184   return 0;
7185 }
7186
7187 //! Auxiliary presentation for an image plane.
7188 class ViewerTest_ImagePrs : public AIS_InteractiveObject
7189 {
7190 public:
7191   //! Main constructor.
7192   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
7193                        const Standard_Real theWidth,
7194                        const Standard_Real theHeight,
7195                        const TCollection_AsciiString& theLabel)
7196   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
7197   {
7198     SetDisplayMode (0);
7199     SetHilightMode (1);
7200     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
7201     {
7202       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
7203       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7204       Graphic3d_MaterialAspect aMat;
7205       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7206       aMat.SetAmbient  (1.0);
7207       aMat.SetDiffuse  (1.0);
7208       aMat.SetSpecular (1.0);
7209       aMat.SetEmissive (1.0);
7210       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
7211       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
7212       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
7213       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
7214       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7215       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
7216       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7217       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7218       aFillAspect->SetFrontMaterial (aMat);
7219       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7220       aFillAspect->SetTextureMapOn();
7221     }
7222     {
7223       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7224       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7225       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7226       myDrawer->SetTextAspect (aTextAspect);
7227     }
7228     {
7229       const gp_Dir aNorm (0.0, 0.0, 1.0);
7230       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7231       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7232       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7233       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7234       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7235       myTris->AddEdge (1);
7236       myTris->AddEdge (2);
7237       myTris->AddEdge (3);
7238       myTris->AddEdge (3);
7239       myTris->AddEdge (2);
7240       myTris->AddEdge (4);
7241
7242       myRect = new Graphic3d_ArrayOfPolylines (4);
7243       myRect->AddVertex (myTris->Vertice (1));
7244       myRect->AddVertex (myTris->Vertice (3));
7245       myRect->AddVertex (myTris->Vertice (4));
7246       myRect->AddVertex (myTris->Vertice (2));
7247     }
7248   }
7249
7250   //! Returns TRUE for accepted display modes.
7251   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7252
7253   //! Compute presentation.
7254   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7255   {
7256     switch (theMode)
7257     {
7258       case 0:
7259       {
7260         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7261         aGroup->AddPrimitiveArray (myTris);
7262         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7263         aGroup->AddPrimitiveArray (myRect);
7264         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7265         return;
7266       }
7267       case 1:
7268       {
7269         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7270         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7271         aGroup->AddPrimitiveArray (myRect);
7272         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7273         return;
7274       }
7275     }
7276   }
7277
7278   //! Compute selection.
7279   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7280   {
7281     if (theMode == 0)
7282     {
7283       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7284       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7285       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7286       theSel->Add (aSensitive);
7287     }
7288   }
7289
7290 private:
7291   Handle(Graphic3d_ArrayOfTriangles) myTris;
7292   Handle(Graphic3d_ArrayOfPolylines) myRect;
7293   TCollection_AsciiString myLabel;
7294   Standard_Real myWidth;
7295   Standard_Real myHeight;
7296 };
7297
7298 //==============================================================================
7299 //function : VDiffImage
7300 //purpose  : The draw-command compares two images.
7301 //==============================================================================
7302
7303 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7304 {
7305   if (theArgNb < 3)
7306   {
7307     std::cout << "Syntax error: not enough arguments.\n";
7308     return 1;
7309   }
7310
7311   Standard_Integer anArgIter = 1;
7312   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7313   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7314   TCollection_AsciiString aDiffImagePath;
7315   Standard_Real    aTolColor        = -1.0;
7316   Standard_Integer toBlackWhite     = -1;
7317   Standard_Integer isBorderFilterOn = -1;
7318   Standard_Boolean isOldSyntax = Standard_False;
7319   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7320   for (; anArgIter < theArgNb; ++anArgIter)
7321   {
7322     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7323     anArg.LowerCase();
7324     if (anArgIter + 1 < theArgNb
7325      && (anArg == "-toleranceofcolor"
7326       || anArg == "-tolerancecolor"
7327       || anArg == "-tolerance"
7328       || anArg == "-toler"))
7329     {
7330       aTolColor = Atof (theArgVec[++anArgIter]);
7331       if (aTolColor < 0.0 || aTolColor > 1.0)
7332       {
7333         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7334         return 1;
7335       }
7336     }
7337     else if (anArg == "-blackwhite")
7338     {
7339       Standard_Boolean toEnable = Standard_True;
7340       if (anArgIter + 1 < theArgNb
7341        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7342       {
7343         ++anArgIter;
7344       }
7345       toBlackWhite = toEnable ? 1 : 0;
7346     }
7347     else if (anArg == "-borderfilter")
7348     {
7349       Standard_Boolean toEnable = Standard_True;
7350       if (anArgIter + 1 < theArgNb
7351        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7352       {
7353         ++anArgIter;
7354       }
7355       isBorderFilterOn = toEnable ? 1 : 0;
7356     }
7357     else if (anArg == "-exitonclose")
7358     {
7359       ViewerTest_EventManager::ToExitOnCloseView() = true;
7360       if (anArgIter + 1 < theArgNb
7361        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7362       {
7363         ++anArgIter;
7364       }
7365     }
7366     else if (anArg == "-closeonescape"
7367           || anArg == "-closeonesc")
7368     {
7369       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7370       if (anArgIter + 1 < theArgNb
7371        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7372       {
7373         ++anArgIter;
7374       }
7375     }
7376     else if (anArgIter + 3 < theArgNb
7377           && anArg == "-display")
7378     {
7379       aViewName   = theArgVec[++anArgIter];
7380       aPrsNameRef = theArgVec[++anArgIter];
7381       aPrsNameNew = theArgVec[++anArgIter];
7382       if (anArgIter + 1 < theArgNb
7383       && *theArgVec[anArgIter + 1] != '-')
7384       {
7385         aPrsNameDiff = theArgVec[++anArgIter];
7386       }
7387     }
7388     else if (aTolColor < 0.0
7389           && anArg.IsRealValue())
7390     {
7391       isOldSyntax = Standard_True;
7392       aTolColor = anArg.RealValue();
7393       if (aTolColor < 0.0 || aTolColor > 1.0)
7394       {
7395         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7396         return 1;
7397       }
7398     }
7399     else if (isOldSyntax
7400           && toBlackWhite == -1
7401           && (anArg == "0" || anArg == "1"))
7402     {
7403       toBlackWhite = anArg == "1" ? 1 : 0;
7404     }
7405     else if (isOldSyntax
7406           && isBorderFilterOn == -1
7407           && (anArg == "0" || anArg == "1"))
7408     {
7409       isBorderFilterOn = anArg == "1" ? 1 : 0;
7410     }
7411     else if (aDiffImagePath.IsEmpty())
7412     {
7413       aDiffImagePath = theArgVec[anArgIter];
7414     }
7415     else
7416     {
7417       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7418       return 1;
7419     }
7420   }
7421
7422   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7423   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7424   if (!anImgRef->Load (anImgPathRef))
7425   {
7426     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7427     return 1;
7428   }
7429   if (!anImgNew->Load (anImgPathNew))
7430   {
7431     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7432     return 1;
7433   }
7434
7435   // compare the images
7436   Image_Diff aComparer;
7437   Standard_Integer aDiffColorsNb = -1;
7438   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7439   {
7440     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7441     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7442     aDiffColorsNb = aComparer.Compare();
7443     theDI << aDiffColorsNb << "\n";
7444   }
7445
7446   // save image of difference
7447   Handle(Image_AlienPixMap) aDiff;
7448   if (aDiffColorsNb > 0
7449   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7450   {
7451     aDiff = new Image_AlienPixMap();
7452     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7453     {
7454       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7455       return 1;
7456     }
7457     aComparer.SaveDiffImage (*aDiff);
7458     if (!aDiffImagePath.IsEmpty()
7459      && !aDiff->Save (aDiffImagePath))
7460     {
7461       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7462       return 1;
7463     }
7464   }
7465
7466   if (aViewName.IsEmpty())
7467   {
7468     return 0;
7469   }
7470
7471   ViewerTest_Names aViewNames (aViewName);
7472   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7473   {
7474     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7475     theDI.Eval (aCommand.ToCString());
7476   }
7477
7478   Standard_Integer aPxLeft = 0;
7479   Standard_Integer aPxTop  = 0;
7480   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7481   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7482                               ? int(anImgRef->SizeY() * 2)
7483                               : int(anImgRef->SizeY());
7484   TCollection_AsciiString aDisplayName;
7485   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7486                                                             aViewName, aDisplayName);
7487
7488   Standard_Real aRatio = anImgRef->Ratio();
7489   Standard_Real aSizeX = 1.0;
7490   Standard_Real aSizeY = aSizeX / aRatio;
7491   {
7492     OSD_Path aPath (anImgPathRef);
7493     TCollection_AsciiString aLabelRef;
7494     if (!aPath.Name().IsEmpty())
7495     {
7496       aLabelRef = aPath.Name() + aPath.Extension();
7497     }
7498     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7499
7500     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7501     gp_Trsf aTrsfRef;
7502     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7503     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7504     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7505   }
7506   {
7507     OSD_Path aPath (anImgPathNew);
7508     TCollection_AsciiString aLabelNew;
7509     if (!aPath.Name().IsEmpty())
7510     {
7511       aLabelNew = aPath.Name() + aPath.Extension();
7512     }
7513     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7514
7515     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7516     gp_Trsf aTrsfRef;
7517     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7518     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7519     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7520   }
7521   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7522   if (!aDiff.IsNull())
7523   {
7524     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7525     gp_Trsf aTrsfDiff;
7526     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7527     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7528   }
7529   if (!aPrsNameDiff.IsEmpty())
7530   {
7531     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7532   }
7533   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7534   ViewerTest::CurrentView()->FitAll();
7535   return 0;
7536 }
7537
7538 //=======================================================================
7539 //function : VSelect
7540 //purpose  : Emulates different types of selection by mouse:
7541 //           1) single click selection
7542 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7543 //           3) selection with polygon having corners at
7544 //           pixel positions (x1,y1),...,(xn,yn)
7545 //           4) any of these selections with shift button pressed
7546 //=======================================================================
7547 static Standard_Integer VSelect (Draw_Interpretor& ,
7548                                  Standard_Integer theNbArgs,
7549                                  const char** theArgVec)
7550 {
7551   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7552   if (aCtx.IsNull())
7553   {
7554     std::cout << "Error: no active View\n";
7555     return 1;
7556   }
7557
7558   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7559   bool isShiftSelection = false, toAllowOverlap = false;
7560   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7561   {
7562     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7563     anArg.LowerCase();
7564     if (anArg == "-allowoverlap")
7565     {
7566       toAllowOverlap = true;
7567       if (anArgIter + 1 < theNbArgs
7568        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7569       {
7570         ++anArgIter;
7571       }
7572     }
7573     else if (anArgIter + 1 < theNbArgs
7574           && anArg.IsIntegerValue()
7575           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7576     {
7577       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7578       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7579     }
7580     else if (anArgIter + 1 == theNbArgs
7581           && anArg.IsIntegerValue())
7582     {
7583       isShiftSelection = anArg.IntegerValue() == 1;
7584     }
7585     else
7586     {
7587       std::cout << "Syntax error at '" << anArg << "'\n";
7588       return 1;
7589     }
7590   }
7591   if (toAllowOverlap
7592    && aPnts.Length() != 2)
7593   {
7594     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7595     return 1;
7596   }
7597   if (toAllowOverlap)
7598   {
7599     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7600   }
7601
7602   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7603   if (aPnts.IsEmpty())
7604   {
7605     if (isShiftSelection)
7606     {
7607       aCtx->ShiftSelect (false);
7608     }
7609     else
7610     {
7611       aCtx->Select (false);
7612     }
7613     aCtx->CurrentViewer()->Invalidate();
7614   }
7615   else if (aPnts.Length() == 2)
7616   {
7617     if (toAllowOverlap
7618      && aPnts.First().y() < aPnts.Last().y())
7619     {
7620       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7621     }
7622     else if (!toAllowOverlap
7623            && aPnts.First().y() > aPnts.Last().y())
7624     {
7625       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7626     }
7627     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7628   }
7629   else
7630   {
7631     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7632   }
7633   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7634   return 0;
7635 }
7636
7637 //=======================================================================
7638 //function : VMoveTo
7639 //purpose  : Emulates cursor movement to defined pixel position
7640 //=======================================================================
7641 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7642                                 Standard_Integer theNbArgs,
7643                                 const char**     theArgVec)
7644 {
7645   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7646   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7647   if (aContext.IsNull())
7648   {
7649     std::cout << "Error: no active View\n";
7650     return 1;
7651   }
7652
7653   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7654   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7655   {
7656     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7657     anArgStr.LowerCase();
7658     if (anArgStr == "-reset"
7659      || anArgStr == "-clear")
7660     {
7661       if (anArgIter + 1 < theNbArgs)
7662       {
7663         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7664         return 1;
7665       }
7666
7667       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7668                                        && aContext->CurrentViewer()->GridEcho();
7669       if (toEchoGrid)
7670       {
7671         aContext->CurrentViewer()->HideGridEcho (aView);
7672       }
7673       if (aContext->ClearDetected() || toEchoGrid)
7674       {
7675         aContext->CurrentViewer()->RedrawImmediate();
7676       }
7677       return 0;
7678     }
7679     else if (aMousePos.x() == IntegerLast()
7680           && anArgStr.IsIntegerValue())
7681     {
7682       aMousePos.x() = anArgStr.IntegerValue();
7683     }
7684     else if (aMousePos.y() == IntegerLast()
7685           && anArgStr.IsIntegerValue())
7686     {
7687       aMousePos.y() = anArgStr.IntegerValue();
7688     }
7689     else
7690     {
7691       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7692       return 1;
7693     }
7694   }
7695
7696   if (aMousePos.x() == IntegerLast()
7697    || aMousePos.y() == IntegerLast())
7698   {
7699     std::cout << "Syntax error: wrong number of arguments\n";
7700     return 1;
7701   }
7702
7703   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7704   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7705   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7706
7707   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7708   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7709   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7710   {
7711     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7712     {
7713       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7714       break;
7715     }
7716   }
7717   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7718   return 0;
7719 }
7720
7721 namespace
7722 {
7723   //! Global map storing all animations registered in ViewerTest.
7724   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7725
7726   //! The animation calling the Draw Harness command.
7727   class ViewerTest_AnimationProc : public AIS_Animation
7728   {
7729   public:
7730
7731     //! Main constructor.
7732     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7733                               Draw_Interpretor* theDI,
7734                               const TCollection_AsciiString& theCommand)
7735     : AIS_Animation (theAnimationName),
7736       myDrawInter(theDI),
7737       myCommand  (theCommand)
7738     {
7739       //
7740     }
7741
7742   protected:
7743
7744     //! Evaluate the command.
7745     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7746     {
7747       TCollection_AsciiString aCmd = myCommand;
7748       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7749       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7750       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7751       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7752       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7753       myDrawInter->Eval (aCmd.ToCString());
7754     }
7755
7756     //! Find the keyword in the command and replace it with value.
7757     //! @return the position of the keyword to pass value
7758     void replace (TCollection_AsciiString&       theCmd,
7759                   const TCollection_AsciiString& theKey,
7760                   const TCollection_AsciiString& theVal)
7761     {
7762       TCollection_AsciiString aCmd (theCmd);
7763       aCmd.LowerCase();
7764       const Standard_Integer aPos = aCmd.Search (theKey);
7765       if (aPos == -1)
7766       {
7767         return;
7768       }
7769
7770       TCollection_AsciiString aPart1, aPart2;
7771       Standard_Integer aPart1To = aPos - 1;
7772       if (aPart1To >= 1
7773        && aPart1To <= theCmd.Length())
7774       {
7775         aPart1 = theCmd.SubString (1, aPart1To);
7776       }
7777
7778       Standard_Integer aPart2From = aPos + theKey.Length();
7779       if (aPart2From >= 1
7780        && aPart2From <= theCmd.Length())
7781       {
7782         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7783       }
7784
7785       theCmd = aPart1 + theVal + aPart2;
7786     }
7787
7788   protected:
7789
7790     Draw_Interpretor*       myDrawInter;
7791     TCollection_AsciiString myCommand;
7792
7793   };
7794
7795   //! Replace the animation with the new one.
7796   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7797                                 Handle(AIS_Animation)&       theAnimation,
7798                                 const Handle(AIS_Animation)& theAnimationNew)
7799   {
7800     theAnimationNew->CopyFrom (theAnimation);
7801     if (!theParentAnimation.IsNull())
7802     {
7803       theParentAnimation->Replace (theAnimation, theAnimationNew);
7804     }
7805     else
7806     {
7807       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7808       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7809     }
7810     theAnimation = theAnimationNew;
7811   }
7812
7813   //! Parse the point.
7814   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7815   {
7816     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7817     if (!anXYZ[0].IsRealValue()
7818      || !anXYZ[1].IsRealValue()
7819      || !anXYZ[2].IsRealValue())
7820     {
7821       return Standard_False;
7822     }
7823
7824     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7825     return Standard_True;
7826   }
7827
7828   //! Parse the quaternion.
7829   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7830   {
7831     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7832     if (!anXYZW[0].IsRealValue()
7833      || !anXYZW[1].IsRealValue()
7834      || !anXYZW[2].IsRealValue()
7835      || !anXYZW[3].IsRealValue())
7836     {
7837       return Standard_False;
7838     }
7839
7840     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7841     return Standard_True;
7842   }
7843
7844   //! Auxiliary class for flipping image upside-down.
7845   class ImageFlipper
7846   {
7847   public:
7848
7849     //! Empty constructor.
7850     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7851
7852     //! Perform flipping.
7853     Standard_Boolean FlipY (Image_PixMap& theImage)
7854     {
7855       if (theImage.IsEmpty()
7856        || theImage.SizeX() == 0
7857        || theImage.SizeY() == 0)
7858       {
7859         return Standard_False;
7860       }
7861
7862       const Standard_Size aRowSize = theImage.SizeRowBytes();
7863       if (myTmp.Size() < aRowSize
7864       && !myTmp.Allocate (aRowSize))
7865       {
7866         return Standard_False;
7867       }
7868
7869       // for odd height middle row should be left as is
7870       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7871       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7872       {
7873         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7874         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7875         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7876         memcpy (aTop,               aBot,         aRowSize);
7877         memcpy (aBot,               myTmp.Data(), aRowSize);
7878       }
7879       return Standard_True;
7880     }
7881
7882   private:
7883     NCollection_Buffer myTmp;
7884   };
7885
7886 }
7887
7888 //=================================================================================================
7889 //function : VViewParams
7890 //purpose  : Gets or sets AIS View characteristics
7891 //=================================================================================================
7892 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7893 {
7894   Handle(V3d_View) aView = ViewerTest::CurrentView();
7895   if (aView.IsNull())
7896   {
7897     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7898     return 1;
7899   }
7900
7901   Standard_Boolean toSetProj     = Standard_False;
7902   Standard_Boolean toSetUp       = Standard_False;
7903   Standard_Boolean toSetAt       = Standard_False;
7904   Standard_Boolean toSetEye      = Standard_False;
7905   Standard_Boolean toSetScale    = Standard_False;
7906   Standard_Boolean toSetSize     = Standard_False;
7907   Standard_Boolean toSetCenter2d = Standard_False;
7908   Standard_Real    aViewScale = aView->Scale();
7909   Standard_Real    aViewSize  = 1.0;
7910   Graphic3d_Vec2i  aCenter2d;
7911   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7912   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7913   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7914   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7915   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7916   if (theArgsNb == 1)
7917   {
7918     // print all of the available view parameters
7919     char aText[4096];
7920     Sprintf (aText,
7921              "Scale: %g\n"
7922              "Proj:  %12g %12g %12g\n"
7923              "Up:    %12g %12g %12g\n"
7924              "At:    %12g %12g %12g\n"
7925              "Eye:   %12g %12g %12g\n",
7926               aViewScale,
7927               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7928               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7929               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7930               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7931     theDi << aText;
7932     return 0;
7933   }
7934
7935   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7936   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7937   {
7938     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7939     anArg.LowerCase();
7940     if (anUpdateTool.parseRedrawMode (anArg))
7941     {
7942       continue;
7943     }
7944     else if (anArg == "-cmd"
7945           || anArg == "-command"
7946           || anArg == "-args")
7947     {
7948       char aText[4096];
7949       Sprintf (aText,
7950                "-scale %g "
7951                "-proj %g %g %g "
7952                "-up %g %g %g "
7953                "-at %g %g %g\n",
7954                 aViewScale,
7955                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7956                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7957                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7958       theDi << aText;
7959     }
7960     else if (anArg == "-scale"
7961           || anArg == "-size")
7962     {
7963       if (anArgIter + 1 < theArgsNb
7964        && *theArgVec[anArgIter + 1] != '-')
7965       {
7966         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7967         if (aValueArg.IsRealValue())
7968         {
7969           ++anArgIter;
7970           if (anArg == "-scale")
7971           {
7972             toSetScale = Standard_True;
7973             aViewScale = aValueArg.RealValue();
7974           }
7975           else if (anArg == "-size")
7976           {
7977             toSetSize = Standard_True;
7978             aViewSize = aValueArg.RealValue();
7979           }
7980           continue;
7981         }
7982       }
7983       if (anArg == "-scale")
7984       {
7985         theDi << "Scale: " << aView->Scale() << "\n";
7986       }
7987       else if (anArg == "-size")
7988       {
7989         Graphic3d_Vec2d aSizeXY;
7990         aView->Size (aSizeXY.x(), aSizeXY.y());
7991         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7992       }
7993     }
7994     else if (anArg == "-eye"
7995           || anArg == "-at"
7996           || anArg == "-up"
7997           || anArg == "-proj")
7998     {
7999       if (anArgIter + 3 < theArgsNb)
8000       {
8001         gp_XYZ anXYZ;
8002         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
8003         {
8004           anArgIter += 3;
8005           if (anArg == "-eye")
8006           {
8007             toSetEye = Standard_True;
8008             aViewEye = anXYZ;
8009           }
8010           else if (anArg == "-at")
8011           {
8012             toSetAt = Standard_True;
8013             aViewAt = anXYZ;
8014           }
8015           else if (anArg == "-up")
8016           {
8017             toSetUp = Standard_True;
8018             aViewUp = anXYZ;
8019           }
8020           else if (anArg == "-proj")
8021           {
8022             toSetProj = Standard_True;
8023             aViewProj = anXYZ;
8024           }
8025           continue;
8026         }
8027       }
8028
8029       if (anArg == "-eye")
8030       {
8031         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8032       }
8033       else if (anArg == "-at")
8034       {
8035         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8036       }
8037       else if (anArg == "-up")
8038       {
8039         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8040       }
8041       else if (anArg == "-proj")
8042       {
8043         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8044       }
8045     }
8046     else if (anArg == "-center")
8047     {
8048       if (anArgIter + 2 < theArgsNb)
8049       {
8050         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8051         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8052         if (anX.IsIntegerValue()
8053          && anY.IsIntegerValue())
8054         {
8055           toSetCenter2d = Standard_True;
8056           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8057         }
8058       }
8059     }
8060     else
8061     {
8062       std::cout << "Syntax error at '" << anArg << "'\n";
8063       return 1;
8064     }
8065   }
8066
8067   // change view parameters in proper order
8068   if (toSetScale)
8069   {
8070     aView->SetScale (aViewScale);
8071   }
8072   if (toSetSize)
8073   {
8074     aView->SetSize (aViewSize);
8075   }
8076   if (toSetEye)
8077   {
8078     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8079   }
8080   if (toSetAt)
8081   {
8082     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8083   }
8084   if (toSetProj)
8085   {
8086     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8087   }
8088   if (toSetUp)
8089   {
8090     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8091   }
8092   if (toSetCenter2d)
8093   {
8094     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8095   }
8096
8097   return 0;
8098 }
8099
8100 //==============================================================================
8101 //function : V2DMode
8102 //purpose  :
8103 //==============================================================================
8104 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8105 {
8106   bool is2dMode = true;
8107   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8108   if (aV3dView.IsNull())
8109   {
8110     std::cout << "Error: no active view.\n";
8111     return 1;
8112   }
8113   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8114   {
8115     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8116     TCollection_AsciiString anArgCase = anArg;
8117     anArgCase.LowerCase();
8118     if (anArgIt + 1 < theArgsNb
8119      && anArgCase == "-name")
8120     {
8121       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8122       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8123       if (!ViewerTest_myViews.IsBound1 (aViewName))
8124       {
8125         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8126         return 1;
8127       }
8128       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8129     }
8130     else if (anArgCase == "-mode")
8131     {
8132       if (anArgIt + 1 < theArgsNb
8133        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8134       {
8135         ++anArgIt;
8136       }
8137     }
8138     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8139     {
8140       //
8141     }
8142     else
8143     {
8144       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8145       return 1;
8146     }
8147   }
8148
8149   aV3dView->SetView2DMode (is2dMode);
8150   return 0;
8151 }
8152
8153 //==============================================================================
8154 //function : VAnimation
8155 //purpose  :
8156 //==============================================================================
8157 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8158                                     Standard_Integer  theArgNb,
8159                                     const char**      theArgVec)
8160 {
8161   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8162   if (theArgNb < 2)
8163   {
8164     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8165          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8166     {
8167       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8168     }
8169     return 0;
8170   }
8171   if (aCtx.IsNull())
8172   {
8173     std::cout << "Error: no active view\n";
8174     return 1;
8175   }
8176
8177   Standard_Integer anArgIter = 1;
8178   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8179   if (aNameArg.IsEmpty())
8180   {
8181     std::cout << "Syntax error: animation name is not defined.\n";
8182     return 1;
8183   }
8184
8185   TCollection_AsciiString aNameArgLower = aNameArg;
8186   aNameArgLower.LowerCase();
8187   if (aNameArgLower == "-reset"
8188    || aNameArgLower == "-clear")
8189   {
8190     ViewerTest_AnimationTimelineMap.Clear();
8191     return 0;
8192   }
8193   else if (aNameArg.Value (1) == '-')
8194   {
8195     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8196     return 1;
8197   }
8198
8199   const char* aNameSplitter = "/";
8200   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8201   if (aSplitPos == -1)
8202   {
8203     aNameSplitter = ".";
8204     aSplitPos = aNameArg.Search (aNameSplitter);
8205   }
8206
8207   // find existing or create a new animation by specified name within syntax "parent.child".
8208   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8209   for (; !aNameArg.IsEmpty();)
8210   {
8211     TCollection_AsciiString aNameParent;
8212     if (aSplitPos != -1)
8213     {
8214       if (aSplitPos == aNameArg.Length())
8215       {
8216         std::cout << "Syntax error: animation name is not defined.\n";
8217         return 1;
8218       }
8219
8220       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8221       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8222
8223       aSplitPos = aNameArg.Search (aNameSplitter);
8224     }
8225     else
8226     {
8227       aNameParent = aNameArg;
8228       aNameArg.Clear();
8229     }
8230
8231     if (anAnimation.IsNull())
8232     {
8233       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8234       {
8235         anAnimation = new AIS_Animation (aNameParent);
8236         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8237       }
8238       aRootAnimation = anAnimation;
8239     }
8240     else
8241     {
8242       aParentAnimation = anAnimation;
8243       anAnimation = aParentAnimation->Find (aNameParent);
8244       if (anAnimation.IsNull())
8245       {
8246         anAnimation = new AIS_Animation (aNameParent);
8247         aParentAnimation->Add (anAnimation);
8248       }
8249     }
8250   }
8251
8252   if (anArgIter >= theArgNb)
8253   {
8254     // just print the list of children
8255     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8256     {
8257       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8258     }
8259     return 0;
8260   }
8261
8262   // animation parameters
8263   Standard_Boolean toPlay = Standard_False;
8264   Standard_Real aPlaySpeed     = 1.0;
8265   Standard_Real aPlayStartTime = anAnimation->StartPts();
8266   Standard_Real aPlayDuration  = anAnimation->Duration();
8267   Standard_Boolean isFreeCamera = Standard_False;
8268   Standard_Boolean isLockLoop   = Standard_False;
8269
8270   // video recording parameters
8271   TCollection_AsciiString aRecFile;
8272   Image_VideoParams aRecParams;
8273
8274   Handle(V3d_View) aView = ViewerTest::CurrentView();
8275   for (; anArgIter < theArgNb; ++anArgIter)
8276   {
8277     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8278     anArg.LowerCase();
8279     // general options
8280     if (anArg == "-reset"
8281      || anArg == "-clear")
8282     {
8283       anAnimation->Clear();
8284     }
8285     else if (anArg == "-remove"
8286           || anArg == "-del"
8287           || anArg == "-delete")
8288     {
8289       if (!aParentAnimation.IsNull())
8290       {
8291         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8292       }
8293       else
8294       {
8295         aParentAnimation->Remove (anAnimation);
8296       }
8297     }
8298     // playback options
8299     else if (anArg == "-play")
8300     {
8301       toPlay = Standard_True;
8302       if (++anArgIter < theArgNb)
8303       {
8304         if (*theArgVec[anArgIter] == '-')
8305         {
8306           --anArgIter;
8307           continue;
8308         }
8309         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8310
8311         if (++anArgIter < theArgNb)
8312         {
8313           if (*theArgVec[anArgIter] == '-')
8314           {
8315             --anArgIter;
8316             continue;
8317           }
8318           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8319         }
8320       }
8321     }
8322     else if (anArg == "-resume")
8323     {
8324       toPlay = Standard_True;
8325       aPlayStartTime = anAnimation->ElapsedTime();
8326       if (++anArgIter < theArgNb)
8327       {
8328         if (*theArgVec[anArgIter] == '-')
8329         {
8330           --anArgIter;
8331           continue;
8332         }
8333
8334         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8335       }
8336     }
8337     else if (anArg == "-playspeed"
8338           || anArg == "-speed")
8339     {
8340       if (++anArgIter >= theArgNb)
8341       {
8342         std::cout << "Syntax error at " << anArg << ".\n";
8343         return 1;
8344       }
8345       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8346     }
8347     else if (anArg == "-lock"
8348           || anArg == "-lockloop"
8349           || anArg == "-playlockloop")
8350     {
8351       isLockLoop = Standard_True;
8352     }
8353     else if (anArg == "-freecamera"
8354           || anArg == "-playfreecamera"
8355           || anArg == "-freelook")
8356     {
8357       isFreeCamera = Standard_True;
8358     }
8359     // video recodring options
8360     else if (anArg == "-rec"
8361           || anArg == "-record")
8362     {
8363       if (++anArgIter >= theArgNb)
8364       {
8365         std::cout << "Syntax error at " << anArg << ".\n";
8366         return 1;
8367       }
8368
8369       aRecFile = theArgVec[anArgIter];
8370       if (aRecParams.FpsNum <= 0)
8371       {
8372         aRecParams.FpsNum = 24;
8373       }
8374
8375       if (anArgIter + 2 < theArgNb
8376       && *theArgVec[anArgIter + 1] != '-'
8377       && *theArgVec[anArgIter + 2] != '-')
8378       {
8379         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8380         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8381         if (aWidthArg .IsIntegerValue()
8382          && aHeightArg.IsIntegerValue())
8383         {
8384           aRecParams.Width  = aWidthArg .IntegerValue();
8385           aRecParams.Height = aHeightArg.IntegerValue();
8386           anArgIter += 2;
8387         }
8388       }
8389     }
8390     else if (anArg == "-fps")
8391     {
8392       if (++anArgIter >= theArgNb)
8393       {
8394         std::cout << "Syntax error at " << anArg << ".\n";
8395         return 1;
8396       }
8397
8398       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8399       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8400       if (aSplitIndex == 0)
8401       {
8402         aRecParams.FpsNum = aFpsArg.IntegerValue();
8403       }
8404       else
8405       {
8406         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8407         aFpsArg.Split (aFpsArg.Length() - 1);
8408         const TCollection_AsciiString aNumStr = aFpsArg;
8409         aRecParams.FpsNum = aNumStr.IntegerValue();
8410         aRecParams.FpsDen = aDenStr.IntegerValue();
8411         if (aRecParams.FpsDen < 1)
8412         {
8413           std::cout << "Syntax error at " << anArg << ".\n";
8414           return 1;
8415         }
8416       }
8417     }
8418     else if (anArg == "-format")
8419     {
8420       if (++anArgIter >= theArgNb)
8421       {
8422         std::cout << "Syntax error at " << anArg << ".\n";
8423         return 1;
8424       }
8425       aRecParams.Format = theArgVec[anArgIter];
8426     }
8427     else if (anArg == "-pix_fmt"
8428           || anArg == "-pixfmt"
8429           || anArg == "-pixelformat")
8430     {
8431       if (++anArgIter >= theArgNb)
8432       {
8433         std::cout << "Syntax error at " << anArg << ".\n";
8434         return 1;
8435       }
8436       aRecParams.PixelFormat = theArgVec[anArgIter];
8437     }
8438     else if (anArg == "-codec"
8439           || anArg == "-vcodec"
8440           || anArg == "-videocodec")
8441     {
8442       if (++anArgIter >= theArgNb)
8443       {
8444         std::cout << "Syntax error at " << anArg << ".\n";
8445         return 1;
8446       }
8447       aRecParams.VideoCodec = theArgVec[anArgIter];
8448     }
8449     else if (anArg == "-crf"
8450           || anArg == "-preset"
8451           || anArg == "-qp")
8452     {
8453       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8454       if (++anArgIter >= theArgNb)
8455       {
8456         std::cout << "Syntax error at " << anArg << ".\n";
8457         return 1;
8458       }
8459
8460       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8461     }
8462     // animation definition options
8463     else if (anArg == "-start"
8464           || anArg == "-starttime"
8465           || anArg == "-startpts")
8466     {
8467       if (++anArgIter >= theArgNb)
8468       {
8469         std::cout << "Syntax error at " << anArg << ".\n";
8470         return 1;
8471       }
8472
8473       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8474       aRootAnimation->UpdateTotalDuration();
8475     }
8476     else if (anArg == "-end"
8477           || anArg == "-endtime"
8478           || anArg == "-endpts")
8479     {
8480       if (++anArgIter >= theArgNb)
8481       {
8482         std::cout << "Syntax error at " << anArg << ".\n";
8483         return 1;
8484       }
8485
8486       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8487       aRootAnimation->UpdateTotalDuration();
8488     }
8489     else if (anArg == "-dur"
8490           || anArg == "-duration")
8491     {
8492       if (++anArgIter >= theArgNb)
8493       {
8494         std::cout << "Syntax error at " << anArg << ".\n";
8495         return 1;
8496       }
8497
8498       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8499       aRootAnimation->UpdateTotalDuration();
8500     }
8501     else if (anArg == "-command"
8502           || anArg == "-cmd"
8503           || anArg == "-invoke"
8504           || anArg == "-eval"
8505           || anArg == "-proc")
8506     {
8507       if (++anArgIter >= theArgNb)
8508       {
8509         std::cout << "Syntax error at " << anArg << ".\n";
8510         return 1;
8511       }
8512
8513       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8514       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8515     }
8516     else if (anArg == "-objecttrsf"
8517           || anArg == "-objectransformation"
8518           || anArg == "-objtransformation"
8519           || anArg == "-objtrsf"
8520           || anArg == "-object"
8521           || anArg == "-obj")
8522     {
8523       if (++anArgIter >= theArgNb)
8524       {
8525         std::cout << "Syntax error at " << anArg << ".\n";
8526         return 1;
8527       }
8528
8529       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8530       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8531       Handle(AIS_InteractiveObject) anObject;
8532       if (!aMapOfAIS.Find2 (anObjName, anObject))
8533       {
8534         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8535         return 1;
8536       }
8537
8538       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8539       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8540       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8541       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8542       Standard_Boolean isTrsfSet = Standard_False;
8543       Standard_Integer aTrsfArgIter = anArgIter + 1;
8544       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8545       {
8546         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8547         aTrsfArg.LowerCase();
8548         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8549         if (aTrsfArg.StartsWith ("-rotation")
8550          || aTrsfArg.StartsWith ("-rot"))
8551         {
8552           isTrsfSet = Standard_True;
8553           if (aTrsfArgIter + 4 >= theArgNb
8554           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8555           {
8556             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8557             return 1;
8558           }
8559           aTrsfArgIter += 4;
8560         }
8561         else if (aTrsfArg.StartsWith ("-location")
8562               || aTrsfArg.StartsWith ("-loc"))
8563         {
8564           isTrsfSet = Standard_True;
8565           if (aTrsfArgIter + 3 >= theArgNb
8566           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8567           {
8568             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8569             return 1;
8570           }
8571           aTrsfArgIter += 3;
8572         }
8573         else if (aTrsfArg.StartsWith ("-scale"))
8574         {
8575           isTrsfSet = Standard_True;
8576           if (++aTrsfArgIter >= theArgNb)
8577           {
8578             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8579             return 1;
8580           }
8581
8582           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8583           if (!aScaleStr.IsRealValue())
8584           {
8585             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8586             return 1;
8587           }
8588           aScales[anIndex] = aScaleStr.RealValue();
8589         }
8590         else
8591         {
8592           anArgIter = aTrsfArgIter - 1;
8593           break;
8594         }
8595       }
8596       if (!isTrsfSet)
8597       {
8598         std::cout << "Syntax error at " << anArg << ".\n";
8599         return 1;
8600       }
8601       else if (aTrsfArgIter >= theArgNb)
8602       {
8603         anArgIter = theArgNb;
8604       }
8605
8606       aTrsfs[0].SetRotation        (aRotQuats[0]);
8607       aTrsfs[1].SetRotation        (aRotQuats[1]);
8608       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8609       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8610       aTrsfs[0].SetScaleFactor     (aScales[0]);
8611       aTrsfs[1].SetScaleFactor     (aScales[1]);
8612
8613       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8614       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8615     }
8616     else if (anArg == "-viewtrsf"
8617           || anArg == "-view")
8618     {
8619       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8620       if (aCamAnimation.IsNull())
8621       {
8622         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8623         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8624       }
8625
8626       Handle(Graphic3d_Camera) aCams[2] =
8627       {
8628         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8629         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8630       };
8631
8632       Standard_Boolean isTrsfSet = Standard_False;
8633       Standard_Integer aViewArgIter = anArgIter + 1;
8634       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8635       {
8636         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8637         aViewArg.LowerCase();
8638         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8639         if (aViewArg.StartsWith ("-scale"))
8640         {
8641           isTrsfSet = Standard_True;
8642           if (++aViewArgIter >= theArgNb)
8643           {
8644             std::cout << "Syntax error at " << anArg << ".\n";
8645             return 1;
8646           }
8647
8648           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8649           if (!aScaleStr.IsRealValue())
8650           {
8651             std::cout << "Syntax error at " << aViewArg << ".\n";
8652             return 1;
8653           }
8654           Standard_Real aScale = aScaleStr.RealValue();
8655           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8656           aCams[anIndex]->SetScale (aScale);
8657         }
8658         else if (aViewArg.StartsWith ("-eye")
8659               || aViewArg.StartsWith ("-center")
8660               || aViewArg.StartsWith ("-at")
8661               || aViewArg.StartsWith ("-up"))
8662         {
8663           isTrsfSet = Standard_True;
8664           gp_XYZ anXYZ;
8665           if (aViewArgIter + 3 >= theArgNb
8666           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8667           {
8668             std::cout << "Syntax error at " << aViewArg << ".\n";
8669             return 1;
8670           }
8671           aViewArgIter += 3;
8672
8673           if (aViewArg.StartsWith ("-eye"))
8674           {
8675             aCams[anIndex]->SetEye (anXYZ);
8676           }
8677           else if (aViewArg.StartsWith ("-center")
8678                 || aViewArg.StartsWith ("-at"))
8679           {
8680             aCams[anIndex]->SetCenter (anXYZ);
8681           }
8682           else if (aViewArg.StartsWith ("-up"))
8683           {
8684             aCams[anIndex]->SetUp (anXYZ);
8685           }
8686         }
8687         else
8688         {
8689           anArgIter = aViewArgIter - 1;
8690           break;
8691         }
8692       }
8693       if (!isTrsfSet)
8694       {
8695         std::cout << "Syntax error at " << anArg << ".\n";
8696         return 1;
8697       }
8698       else if (aViewArgIter >= theArgNb)
8699       {
8700         anArgIter = theArgNb;
8701       }
8702
8703       aCamAnimation->SetCameraStart(aCams[0]);
8704       aCamAnimation->SetCameraEnd  (aCams[1]);
8705     }
8706     else
8707     {
8708       std::cout << "Syntax error at " << anArg << ".\n";
8709       return 1;
8710     }
8711   }
8712
8713   if (!toPlay && aRecFile.IsEmpty())
8714   {
8715     return 0;
8716   }
8717
8718   // Start animation timeline and process frame updating.
8719   TheIsAnimating = Standard_True;
8720   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8721   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8722   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8723   if (isFreeCamera)
8724   {
8725     aView->Camera()->Copy (aCameraBack);
8726   }
8727
8728   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8729   if (aRecParams.FpsNum <= 0)
8730   {
8731     while (!anAnimation->IsStopped())
8732     {
8733       aCameraBack->Copy (aView->Camera());
8734       const Standard_Real aPts = anAnimation->UpdateTimer();
8735       if (isFreeCamera)
8736       {
8737         aView->Camera()->Copy (aCameraBack);
8738       }
8739
8740       if (aPts >= anUpperPts)
8741       {
8742         anAnimation->Pause();
8743         break;
8744       }
8745
8746       if (aView->IsInvalidated())
8747       {
8748         aView->Redraw();
8749       }
8750       else
8751       {
8752         aView->RedrawImmediate();
8753       }
8754
8755       if (!isLockLoop)
8756       {
8757         // handle user events
8758         theDI.Eval ("after 1 set waiter 1");
8759         theDI.Eval ("vwait waiter");
8760       }
8761       if (!TheIsAnimating)
8762       {
8763         anAnimation->Pause();
8764         theDI << aPts;
8765         break;
8766       }
8767     }
8768
8769     if (aView->IsInvalidated())
8770     {
8771       aView->Redraw();
8772     }
8773     else
8774     {
8775       aView->RedrawImmediate();
8776     }
8777   }
8778   else
8779   {
8780     OSD_Timer aPerfTimer;
8781     aPerfTimer.Start();
8782
8783     Handle(Image_VideoRecorder) aRecorder;
8784     ImageFlipper aFlipper;
8785     Handle(Draw_ProgressIndicator) aProgress;
8786     if (!aRecFile.IsEmpty())
8787     {
8788       if (aRecParams.Width  <= 0
8789        || aRecParams.Height <= 0)
8790       {
8791         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8792       }
8793
8794       aRecorder = new Image_VideoRecorder();
8795       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8796       {
8797         std::cout << "Error: failed to open video file for recording\n";
8798         return 0;
8799       }
8800
8801       aProgress = new Draw_ProgressIndicator (theDI, 1);
8802     }
8803
8804     // Manage frame-rated animation here
8805     Standard_Real aPts = aPlayStartTime;
8806     int64_t aNbFrames = 0;
8807     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8808     Standard_Integer aSecondsProgress = 0;
8809     for (; aPts <= anUpperPts && aPSentry.More();)
8810     {
8811       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8812       aPts = aPlayStartTime + aRecPts;
8813       ++aNbFrames;
8814       if (!anAnimation->Update (aPts))
8815       {
8816         break;
8817       }
8818
8819       if (!aRecorder.IsNull())
8820       {
8821         V3d_ImageDumpOptions aDumpParams;
8822         aDumpParams.Width          = aRecParams.Width;
8823         aDumpParams.Height         = aRecParams.Height;
8824         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8825         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8826         aDumpParams.ToAdjustAspect = Standard_True;
8827         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8828         {
8829           std::cout << "Error: view dump is failed!\n";
8830           return 0;
8831         }
8832         aFlipper.FlipY (aRecorder->ChangeFrame());
8833         if (!aRecorder->PushFrame())
8834         {
8835           return 0;
8836         }
8837       }
8838       else
8839       {
8840         aView->Redraw();
8841       }
8842
8843       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8844       {
8845         aPSentry.Next();
8846         ++aSecondsProgress;
8847       }
8848     }
8849
8850     aPerfTimer.Stop();
8851     anAnimation->Stop();
8852     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8853     theDI << "Average FPS: " << aRecFps << "\n"
8854           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8855
8856     aView->Redraw();
8857   }
8858
8859   aView->SetImmediateUpdate (wasImmediateUpdate);
8860   TheIsAnimating = Standard_False;
8861   return 0;
8862 }
8863
8864
8865 //=======================================================================
8866 //function : VChangeSelected
8867 //purpose  : Adds the shape to selection or remove one from it
8868 //=======================================================================
8869 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8870                                 Standard_Integer argc,
8871                                 const char ** argv)
8872 {
8873   if(argc != 2)
8874   {
8875     di<<"Usage : " << argv[0] << " shape \n";
8876     return 1;
8877   }
8878   //get AIS_Shape:
8879   TCollection_AsciiString aName(argv[1]);
8880   Handle(AIS_InteractiveObject) anAISObject;
8881   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8882     || anAISObject.IsNull())
8883   {
8884     di<<"Use 'vdisplay' before";
8885     return 1;
8886   }
8887
8888   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8889   return 0;
8890 }
8891
8892 //=======================================================================
8893 //function : VNbSelected
8894 //purpose  : Returns number of selected objects
8895 //=======================================================================
8896 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8897                                 Standard_Integer argc,
8898                                 const char ** argv)
8899 {
8900   if(argc != 1)
8901   {
8902     di << "Usage : " << argv[0] << "\n";
8903     return 1;
8904   }
8905   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8906   if(aContext.IsNull())
8907   {
8908     di << "use 'vinit' command before " << argv[0] << "\n";
8909     return 1;
8910   }
8911   di << aContext->NbSelected() << "\n";
8912   return 0;
8913 }
8914
8915 //=======================================================================
8916 //function : VPurgeDisplay
8917 //purpose  : Switches altialiasing on or off
8918 //=======================================================================
8919 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8920                                 Standard_Integer argc,
8921                                 const char ** argv)
8922 {
8923   if (argc > 1)
8924   {
8925     di << "Usage : " << argv[0] << "\n";
8926     return 1;
8927   }
8928   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8929   if (aContext.IsNull())
8930   {
8931     di << "use 'vinit' command before " << argv[0] << "\n";
8932     return 1;
8933   }
8934
8935   di << aContext->PurgeDisplay() << "\n";
8936   return 0;
8937 }
8938
8939 //=======================================================================
8940 //function : VSetViewSize
8941 //purpose  :
8942 //=======================================================================
8943 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8944                                 Standard_Integer argc,
8945                                 const char ** argv)
8946 {
8947   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8948   if(aContext.IsNull())
8949   {
8950     di << "use 'vinit' command before " << argv[0] << "\n";
8951     return 1;
8952   }
8953   if(argc != 2)
8954   {
8955     di<<"Usage : " << argv[0] << " Size\n";
8956     return 1;
8957   }
8958   Standard_Real aSize = Draw::Atof (argv[1]);
8959   if (aSize <= 0.)
8960   {
8961     di<<"Bad Size value  : " << aSize << "\n";
8962     return 1;
8963   }
8964
8965   Handle(V3d_View) aView = ViewerTest::CurrentView();
8966   aView->SetSize(aSize);
8967   return 0;
8968 }
8969
8970 //=======================================================================
8971 //function : VMoveView
8972 //purpose  :
8973 //=======================================================================
8974 static Standard_Integer VMoveView (Draw_Interpretor& di,
8975                                 Standard_Integer argc,
8976                                 const char ** argv)
8977 {
8978   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8979   if(aContext.IsNull())
8980   {
8981     di << "use 'vinit' command before " << argv[0] << "\n";
8982     return 1;
8983   }
8984   if(argc < 4 || argc > 5)
8985   {
8986     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8987     return 1;
8988   }
8989   Standard_Real Dx = Draw::Atof (argv[1]);
8990   Standard_Real Dy = Draw::Atof (argv[2]);
8991   Standard_Real Dz = Draw::Atof (argv[3]);
8992   Standard_Boolean aStart = Standard_True;
8993   if (argc == 5)
8994   {
8995       aStart = (Draw::Atoi (argv[4]) > 0);
8996   }
8997
8998   Handle(V3d_View) aView = ViewerTest::CurrentView();
8999   aView->Move(Dx,Dy,Dz,aStart);
9000   return 0;
9001 }
9002
9003 //=======================================================================
9004 //function : VTranslateView
9005 //purpose  :
9006 //=======================================================================
9007 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9008                                 Standard_Integer argc,
9009                                 const char ** argv)
9010 {
9011   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9012   if(aContext.IsNull())
9013   {
9014     di << "use 'vinit' command before " << argv[0] << "\n";
9015     return 1;
9016   }
9017   if(argc < 4 || argc > 5)
9018   {
9019     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9020     return 1;
9021   }
9022   Standard_Real Dx = Draw::Atof (argv[1]);
9023   Standard_Real Dy = Draw::Atof (argv[2]);
9024   Standard_Real Dz = Draw::Atof (argv[3]);
9025   Standard_Boolean aStart = Standard_True;
9026   if (argc == 5)
9027   {
9028       aStart = (Draw::Atoi (argv[4]) > 0);
9029   }
9030
9031   Handle(V3d_View) aView = ViewerTest::CurrentView();
9032   aView->Translate(Dx,Dy,Dz,aStart);
9033   return 0;
9034 }
9035
9036 //=======================================================================
9037 //function : VTurnView
9038 //purpose  :
9039 //=======================================================================
9040 static Standard_Integer VTurnView (Draw_Interpretor& di,
9041                                 Standard_Integer argc,
9042                                 const char ** argv)
9043 {
9044   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9045   if(aContext.IsNull()) {
9046     di << "use 'vinit' command before " << argv[0] << "\n";
9047     return 1;
9048   }
9049   if(argc < 4 || argc > 5){
9050     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9051     return 1;
9052   }
9053   Standard_Real Ax = Draw::Atof (argv[1]);
9054   Standard_Real Ay = Draw::Atof (argv[2]);
9055   Standard_Real Az = Draw::Atof (argv[3]);
9056   Standard_Boolean aStart = Standard_True;
9057   if (argc == 5)
9058   {
9059       aStart = (Draw::Atoi (argv[4]) > 0);
9060   }
9061
9062   Handle(V3d_View) aView = ViewerTest::CurrentView();
9063   aView->Turn(Ax,Ay,Az,aStart);
9064   return 0;
9065 }
9066
9067 //==============================================================================
9068 //function : VTextureEnv
9069 //purpose  : ENables or disables environment mapping
9070 //==============================================================================
9071 class OCC_TextureEnv : public Graphic3d_TextureEnv
9072 {
9073 public:
9074   OCC_TextureEnv(const Standard_CString FileName);
9075   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9076   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9077                             const Standard_Boolean theModulateFlag,
9078                             const Graphic3d_TypeOfTextureFilter theFilter,
9079                             const Standard_ShortReal theXScale,
9080                             const Standard_ShortReal theYScale,
9081                             const Standard_ShortReal theXShift,
9082                             const Standard_ShortReal theYShift,
9083                             const Standard_ShortReal theAngle);
9084   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9085 };
9086 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9087
9088 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9089   : Graphic3d_TextureEnv(theFileName)
9090 {
9091 }
9092
9093 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9094   : Graphic3d_TextureEnv(theTexId)
9095 {
9096 }
9097
9098 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9099                                           const Standard_Boolean theModulateFlag,
9100                                           const Graphic3d_TypeOfTextureFilter theFilter,
9101                                           const Standard_ShortReal theXScale,
9102                                           const Standard_ShortReal theYScale,
9103                                           const Standard_ShortReal theXShift,
9104                                           const Standard_ShortReal theYShift,
9105                                           const Standard_ShortReal theAngle)
9106 {
9107   myParams->SetRepeat     (theRepeatFlag);
9108   myParams->SetModulate   (theModulateFlag);
9109   myParams->SetFilter     (theFilter);
9110   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9111   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9112   myParams->SetRotation   (theAngle);
9113 }
9114
9115 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9116 {
9117   // get the active view
9118   Handle(V3d_View) aView = ViewerTest::CurrentView();
9119   if (aView.IsNull())
9120   {
9121     std::cerr << "No active view. Please call vinit.\n";
9122     return 1;
9123   }
9124
9125   // Checking the input arguments
9126   Standard_Boolean anEnableFlag = Standard_False;
9127   Standard_Boolean isOk         = theArgNb >= 2;
9128   if (isOk)
9129   {
9130     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9131     anEnableFlag = anEnableOpt.IsEqual("on");
9132     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9133   }
9134   if (anEnableFlag)
9135   {
9136     isOk = (theArgNb == 3 || theArgNb == 11);
9137     if (isOk)
9138     {
9139       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9140       isOk = (!aTextureOpt.IsIntegerValue() ||
9141              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9142
9143       if (isOk && theArgNb == 11)
9144       {
9145         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9146                                 aModulateOpt(theArgVec[4]),
9147                                 aFilterOpt  (theArgVec[5]),
9148                                 aSScaleOpt  (theArgVec[6]),
9149                                 aTScaleOpt  (theArgVec[7]),
9150                                 aSTransOpt  (theArgVec[8]),
9151                                 aTTransOpt  (theArgVec[9]),
9152                                 anAngleOpt  (theArgVec[10]);
9153         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9154                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9155                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9156                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9157                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9158                 anAngleOpt.IsRealValue());
9159       }
9160     }
9161   }
9162
9163   if (!isOk)
9164   {
9165     std::cerr << "Usage :" << std::endl;
9166     std::cerr << theArgVec[0] << " off" << std::endl;
9167     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;
9168     return 1;
9169   }
9170
9171   if (anEnableFlag)
9172   {
9173     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9174     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9175                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9176                                      new OCC_TextureEnv(theArgVec[2]);
9177
9178     if (theArgNb == 11)
9179     {
9180       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9181       aTexEnv->SetTextureParameters(
9182         aRepeatOpt.  IsEqual("repeat"),
9183         aModulateOpt.IsEqual("modulate"),
9184         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9185                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9186                                                                            Graphic3d_TOTF_TRILINEAR,
9187         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9188         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9189         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9190         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9191         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9192         );
9193     }
9194     aView->SetTextureEnv(aTexEnv);
9195   }
9196   else // Disabling environment mapping
9197   {
9198     Handle(Graphic3d_TextureEnv) aTexture;
9199     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9200   }
9201
9202   aView->Redraw();
9203   return 0;
9204 }
9205
9206 namespace
9207 {
9208   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9209
9210   //! Remove registered clipping plane from all views and objects.
9211   static void removePlane (MapOfPlanes& theRegPlanes,
9212                            const TCollection_AsciiString& theName)
9213   {
9214     Handle(Graphic3d_ClipPlane) aClipPlane;
9215     if (!theRegPlanes.Find (theName, aClipPlane))
9216     {
9217       std::cout << "Warning: no such plane.\n";
9218       return;
9219     }
9220
9221     theRegPlanes.UnBind (theName);
9222     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9223          anIObjIt.More(); anIObjIt.Next())
9224     {
9225       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9226       aPrs->RemoveClipPlane (aClipPlane);
9227     }
9228
9229     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9230          aViewIt.More(); aViewIt.Next())
9231     {
9232       const Handle(V3d_View)& aView = aViewIt.Key2();
9233       aView->RemoveClipPlane(aClipPlane);
9234     }
9235
9236     ViewerTest::RedrawAllViews();
9237   }
9238 }
9239
9240 //===============================================================================================
9241 //function : VClipPlane
9242 //purpose  :
9243 //===============================================================================================
9244 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9245 {
9246   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9247   static MapOfPlanes aRegPlanes;
9248
9249   if (theArgsNb < 2)
9250   {
9251     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9252     {
9253       theDi << aPlaneIter.Key() << " ";
9254     }
9255     return 0;
9256   }
9257
9258   TCollection_AsciiString aCommand (theArgVec[1]);
9259   aCommand.LowerCase();
9260   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9261   if (anActiveView.IsNull())
9262   {
9263     std::cout << "Error: no active view.\n";
9264     return 1;
9265   }
9266
9267   // print maximum number of planes for current viewer
9268   if (aCommand == "-maxplanes"
9269    || aCommand == "maxplanes")
9270   {
9271     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9272           << " plane slots provided by driver.\n";
9273     return 0;
9274   }
9275
9276   // create / delete plane instance
9277   if (aCommand == "-create"
9278    || aCommand == "create"
9279    || aCommand == "-delete"
9280    || aCommand == "delete"
9281    || aCommand == "-clone"
9282    || aCommand == "clone")
9283   {
9284     if (theArgsNb < 3)
9285     {
9286       std::cout << "Syntax error: plane name is required.\n";
9287       return 1;
9288     }
9289
9290     Standard_Boolean toCreate = aCommand == "-create"
9291                              || aCommand == "create";
9292     Standard_Boolean toClone  = aCommand == "-clone"
9293                              || aCommand == "clone";
9294     Standard_Boolean toDelete = aCommand == "-delete"
9295                              || aCommand == "delete";
9296     TCollection_AsciiString aPlane (theArgVec[2]);
9297
9298     if (toCreate)
9299     {
9300       if (aRegPlanes.IsBound (aPlane))
9301       {
9302         std::cout << "Warning: existing plane has been overridden.\n";
9303         toDelete = true;
9304       }
9305       else
9306       {
9307         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9308         return 0;
9309       }
9310     }
9311     else if (toClone) // toClone
9312     {
9313       if (!aRegPlanes.IsBound (aPlane))
9314       {
9315         std::cout << "Error: no such plane.\n";
9316         return 1;
9317       }
9318       else if (theArgsNb < 4)
9319       {
9320         std::cout << "Syntax error: enter name for new plane.\n";
9321         return 1;
9322       }
9323
9324       TCollection_AsciiString aClone (theArgVec[3]);
9325       if (aRegPlanes.IsBound (aClone))
9326       {
9327         std::cout << "Error: plane name is in use.\n";
9328         return 1;
9329       }
9330
9331       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9332
9333       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9334       return 0;
9335     }
9336
9337     if (toDelete)
9338     {
9339       if (aPlane == "ALL"
9340        || aPlane == "all"
9341        || aPlane == "*")
9342       {
9343         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9344         {
9345           aPlane = aPlaneIter.Key();
9346           removePlane (aRegPlanes, aPlane);
9347           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9348         }
9349       }
9350       else
9351       {
9352         removePlane (aRegPlanes, aPlane);
9353       }
9354     }
9355
9356     if (toCreate)
9357     {
9358       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9359     }
9360     return 0;
9361   }
9362
9363   // set / unset plane command
9364   if (aCommand == "set"
9365    || aCommand == "unset")
9366   {
9367     if (theArgsNb < 5)
9368     {
9369       std::cout << "Syntax error: need more arguments.\n";
9370       return 1;
9371     }
9372
9373     // redirect to new syntax
9374     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9375     anArgVec.SetValue (1, theArgVec[0]);
9376     anArgVec.SetValue (2, theArgVec[2]);
9377     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9378     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9379     {
9380       anArgVec.SetValue (anIt, theArgVec[anIt]);
9381     }
9382
9383     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9384   }
9385
9386   // change plane command
9387   TCollection_AsciiString aPlaneName;
9388   Handle(Graphic3d_ClipPlane) aClipPlane;
9389   Standard_Integer anArgIter = 0;
9390   if (aCommand == "-change"
9391    || aCommand == "change")
9392   {
9393     // old syntax support
9394     if (theArgsNb < 3)
9395     {
9396       std::cout << "Syntax error: need more arguments.\n";
9397       return 1;
9398     }
9399
9400     anArgIter  = 3;
9401     aPlaneName = theArgVec[2];
9402     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9403     {
9404       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9405       return 1;
9406     }
9407   }
9408   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9409   {
9410     anArgIter  = 2;
9411     aPlaneName = theArgVec[1];
9412   }
9413   else
9414   {
9415     anArgIter  = 2;
9416     aPlaneName = theArgVec[1];
9417     aClipPlane = new Graphic3d_ClipPlane();
9418     aRegPlanes.Bind (aPlaneName, aClipPlane);
9419     theDi << "Created new plane " << aPlaneName << ".\n";
9420   }
9421
9422   if (theArgsNb - anArgIter < 1)
9423   {
9424     std::cout << "Syntax error: need more arguments.\n";
9425     return 1;
9426   }
9427
9428   for (; anArgIter < theArgsNb; ++anArgIter)
9429   {
9430     const char**     aChangeArgs   = theArgVec + anArgIter;
9431     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9432     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9433     aChangeArg.LowerCase();
9434
9435     Standard_Boolean toEnable = Standard_True;
9436     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9437     {
9438       aClipPlane->SetOn (toEnable);
9439     }
9440     else if (aChangeArg.StartsWith ("-equation")
9441           || aChangeArg.StartsWith ("equation"))
9442     {
9443       if (aNbChangeArgs < 5)
9444       {
9445         std::cout << "Syntax error: need more arguments.\n";
9446         return 1;
9447       }
9448
9449       Standard_Integer aSubIndex = 1;
9450       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9451       if (aPrefixLen < aChangeArg.Length())
9452       {
9453         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9454         if (!aSubStr.IsIntegerValue()
9455           || aSubStr.IntegerValue() <= 0)
9456         {
9457           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9458           return 1;
9459         }
9460         aSubIndex = aSubStr.IntegerValue();
9461       }
9462
9463       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9464       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9465       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9466       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9467       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9468       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9469       {
9470         if (aSubPln->ChainNextPlane().IsNull())
9471         {
9472           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9473         }
9474         aSubPln = aSubPln->ChainNextPlane();
9475       }
9476       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9477       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9478       anArgIter += 4;
9479     }
9480     else if ((aChangeArg == "-boxinterior"
9481            || aChangeArg == "-boxint"
9482            || aChangeArg == "-box")
9483             && aNbChangeArgs >= 7)
9484     {
9485       Graphic3d_BndBox3d aBndBox;
9486       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9487       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9488       anArgIter += 6;
9489
9490       Standard_Integer aNbSubPlanes = 6;
9491       const Graphic3d_Vec3d aDirArray[6] =
9492       {
9493         Graphic3d_Vec3d (-1, 0, 0),
9494         Graphic3d_Vec3d ( 1, 0, 0),
9495         Graphic3d_Vec3d ( 0,-1, 0),
9496         Graphic3d_Vec3d ( 0, 1, 0),
9497         Graphic3d_Vec3d ( 0, 0,-1),
9498         Graphic3d_Vec3d ( 0, 0, 1),
9499       };
9500       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9501       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9502       {
9503         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9504         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9505         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9506         if (aSubPlaneIter + 1 == aNbSubPlanes)
9507         {
9508           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9509         }
9510         else
9511         {
9512           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9513         }
9514         aSubPln = aSubPln->ChainNextPlane();
9515       }
9516     }
9517     else if (aChangeArg == "-capping"
9518           || aChangeArg == "capping")
9519     {
9520       if (aNbChangeArgs < 2)
9521       {
9522         std::cout << "Syntax error: need more arguments.\n";
9523         return 1;
9524       }
9525
9526       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9527       {
9528         aClipPlane->SetCapping (toEnable);
9529         anArgIter += 1;
9530       }
9531       else
9532       {
9533         // just skip otherwise (old syntax)
9534       }
9535     }
9536     else if (aChangeArg == "-useobjectmaterial"
9537           || aChangeArg == "-useobjectmat"
9538           || aChangeArg == "-useobjmat"
9539           || aChangeArg == "-useobjmaterial")
9540     {
9541       if (aNbChangeArgs < 2)
9542       {
9543         std::cout << "Syntax error: need more arguments.\n";
9544         return 1;
9545       }
9546
9547       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9548       {
9549         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9550         anArgIter += 1;
9551       }
9552     }
9553     else if (aChangeArg == "-useobjecttexture"
9554           || aChangeArg == "-useobjecttex"
9555           || aChangeArg == "-useobjtexture"
9556           || aChangeArg == "-useobjtex")
9557     {
9558       if (aNbChangeArgs < 2)
9559       {
9560         std::cout << "Syntax error: need more arguments.\n";
9561         return 1;
9562       }
9563
9564       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9565       {
9566         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9567         anArgIter += 1;
9568       }
9569     }
9570     else if (aChangeArg == "-useobjectshader"
9571           || aChangeArg == "-useobjshader")
9572     {
9573       if (aNbChangeArgs < 2)
9574       {
9575         std::cout << "Syntax error: need more arguments.\n";
9576         return 1;
9577       }
9578
9579       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9580       {
9581         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9582         anArgIter += 1;
9583       }
9584     }
9585     else if (aChangeArg == "-color"
9586           || aChangeArg == "color")
9587     {
9588       Quantity_Color aColor;
9589       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9590                                                            aChangeArgs + 1,
9591                                                            aColor);
9592       if (aNbParsed == 0)
9593       {
9594         std::cout << "Syntax error: need more arguments.\n";
9595         return 1;
9596       }
9597
9598       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9599       aMat.SetAmbientColor (aColor);
9600       aMat.SetDiffuseColor (aColor);
9601       aClipPlane->SetCappingMaterial (aMat);
9602       anArgIter += aNbParsed;
9603     }
9604     else if ((aChangeArg == "-transparency"
9605            || aChangeArg == "-transp")
9606           && aNbChangeArgs >= 2)
9607     {
9608       TCollection_AsciiString aValStr (aChangeArgs[1]);
9609       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9610       if (aValStr.IsRealValue())
9611       {
9612         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9613         aMat.SetTransparency ((float )aValStr.RealValue());
9614         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9615         aClipPlane->SetCappingMaterial (aMat);
9616       }
9617       else
9618       {
9619         aValStr.LowerCase();
9620         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9621         if (aValStr == "opaque")
9622         {
9623           aMode = Graphic3d_AlphaMode_Opaque;
9624         }
9625         else if (aValStr == "mask")
9626         {
9627           aMode = Graphic3d_AlphaMode_Mask;
9628         }
9629         else if (aValStr == "blend")
9630         {
9631           aMode = Graphic3d_AlphaMode_Blend;
9632         }
9633         else if (aValStr == "blendauto")
9634         {
9635           aMode = Graphic3d_AlphaMode_BlendAuto;
9636         }
9637         else
9638         {
9639           std::cout << "Syntax error at '" << aValStr << "'\n";
9640           return 1;
9641         }
9642         anAspect->SetAlphaMode (aMode);
9643         aClipPlane->SetCappingAspect (anAspect);
9644       }
9645       anArgIter += 1;
9646     }
9647     else if (aChangeArg == "-texname"
9648           || aChangeArg == "texname")
9649     {
9650       if (aNbChangeArgs < 2)
9651       {
9652         std::cout << "Syntax error: need more arguments.\n";
9653         return 1;
9654       }
9655
9656       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9657       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9658       if (!aTexture->IsDone())
9659       {
9660         aClipPlane->SetCappingTexture (NULL);
9661       }
9662       else
9663       {
9664         aTexture->EnableModulate();
9665         aTexture->EnableRepeat();
9666         aClipPlane->SetCappingTexture (aTexture);
9667       }
9668       anArgIter += 1;
9669     }
9670     else if (aChangeArg == "-texscale"
9671           || aChangeArg == "texscale")
9672     {
9673       if (aClipPlane->CappingTexture().IsNull())
9674       {
9675         std::cout << "Error: no texture is set.\n";
9676         return 1;
9677       }
9678
9679       if (aNbChangeArgs < 3)
9680       {
9681         std::cout << "Syntax error: need more arguments.\n";
9682         return 1;
9683       }
9684
9685       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9686       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9687       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9688       anArgIter += 2;
9689     }
9690     else if (aChangeArg == "-texorigin"
9691           || aChangeArg == "texorigin") // texture origin
9692     {
9693       if (aClipPlane->CappingTexture().IsNull())
9694       {
9695         std::cout << "Error: no texture is set.\n";
9696         return 1;
9697       }
9698
9699       if (aNbChangeArgs < 3)
9700       {
9701         std::cout << "Syntax error: need more arguments.\n";
9702         return 1;
9703       }
9704
9705       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9706       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9707
9708       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9709       anArgIter += 2;
9710     }
9711     else if (aChangeArg == "-texrotate"
9712           || aChangeArg == "texrotate") // texture rotation
9713     {
9714       if (aClipPlane->CappingTexture().IsNull())
9715       {
9716         std::cout << "Error: no texture is set.\n";
9717         return 1;
9718       }
9719
9720       if (aNbChangeArgs < 2)
9721       {
9722         std::cout << "Syntax error: need more arguments.\n";
9723         return 1;
9724       }
9725
9726       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9727       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9728       anArgIter += 1;
9729     }
9730     else if (aChangeArg == "-hatch"
9731           || aChangeArg == "hatch")
9732     {
9733       if (aNbChangeArgs < 2)
9734       {
9735         std::cout << "Syntax error: need more arguments.\n";
9736         return 1;
9737       }
9738
9739       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9740       aHatchStr.LowerCase();
9741       if (aHatchStr == "on")
9742       {
9743         aClipPlane->SetCappingHatchOn();
9744       }
9745       else if (aHatchStr == "off")
9746       {
9747         aClipPlane->SetCappingHatchOff();
9748       }
9749       else
9750       {
9751         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9752       }
9753       anArgIter += 1;
9754     }
9755     else if (aChangeArg == "-delete"
9756           || aChangeArg == "delete")
9757     {
9758       removePlane (aRegPlanes, aPlaneName);
9759       return 0;
9760     }
9761     else if (aChangeArg == "-set"
9762           || aChangeArg == "-unset"
9763           || aChangeArg == "-setoverrideglobal")
9764     {
9765       // set / unset plane command
9766       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9767       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9768       Standard_Integer anIt = 1;
9769       for (; anIt < aNbChangeArgs; ++anIt)
9770       {
9771         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9772         if (anEntityName.IsEmpty()
9773          || anEntityName.Value (1) == '-')
9774         {
9775           break;
9776         }
9777         else if (!toOverrideGlobal
9778                && ViewerTest_myViews.IsBound1 (anEntityName))
9779         {
9780           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9781           if (toSet)
9782           {
9783             aView->AddClipPlane (aClipPlane);
9784           }
9785           else
9786           {
9787             aView->RemoveClipPlane (aClipPlane);
9788           }
9789           continue;
9790         }
9791         else if (GetMapOfAIS().IsBound2 (anEntityName))
9792         {
9793           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9794           if (toSet)
9795           {
9796             aIObj->AddClipPlane (aClipPlane);
9797           }
9798           else
9799           {
9800             aIObj->RemoveClipPlane (aClipPlane);
9801           }
9802           if (!aIObj->ClipPlanes().IsNull())
9803           {
9804             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9805           }
9806         }
9807         else
9808         {
9809           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9810           return 1;
9811         }
9812       }
9813
9814       if (anIt == 1)
9815       {
9816         // apply to active view
9817         if (toSet)
9818         {
9819           anActiveView->AddClipPlane (aClipPlane);
9820         }
9821         else
9822         {
9823           anActiveView->RemoveClipPlane (aClipPlane);
9824         }
9825       }
9826       else
9827       {
9828         anArgIter = anArgIter + anIt - 1;
9829       }
9830     }
9831     else
9832     {
9833       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9834       return 1;
9835     }
9836   }
9837
9838   ViewerTest::RedrawAllViews();
9839   return 0;
9840 }
9841
9842 //===============================================================================================
9843 //function : VZRange
9844 //purpose  :
9845 //===============================================================================================
9846 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9847 {
9848   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9849
9850   if (aCurrentView.IsNull())
9851   {
9852     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9853     return 1;
9854   }
9855
9856   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9857
9858   if (theArgsNb < 2)
9859   {
9860     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9861     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9862     return 0;
9863   }
9864
9865   if (theArgsNb == 3)
9866   {
9867     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9868     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9869
9870     if (aNewZNear >= aNewZFar)
9871     {
9872       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9873       return 1;
9874     }
9875
9876     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9877     {
9878       std::cout << theArgVec[0] << ": invalid arguments: ";
9879       std::cout << "znear, zfar should be positive for perspective camera.\n";
9880       return 1;
9881     }
9882
9883     aCamera->SetZRange (aNewZNear, aNewZFar);
9884   }
9885   else
9886   {
9887     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9888     return 1;
9889   }
9890
9891   aCurrentView->Redraw();
9892
9893   return 0;
9894 }
9895
9896 //===============================================================================================
9897 //function : VAutoZFit
9898 //purpose  :
9899 //===============================================================================================
9900 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9901 {
9902   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9903
9904   if (aCurrentView.IsNull())
9905   {
9906     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9907     return 1;
9908   }
9909
9910   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9911
9912   if (theArgsNb > 3)
9913   {
9914     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9915     return 1;
9916   }
9917
9918   if (theArgsNb < 2)
9919   {
9920     theDi << "Auto z-fit mode: \n"
9921           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9922           << "Scale: " << aScale << "\n";
9923     return 0;
9924   }
9925
9926   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9927
9928   if (theArgsNb >= 3)
9929   {
9930     aScale = Draw::Atoi (theArgVec[2]);
9931   }
9932
9933   aCurrentView->SetAutoZFitMode (isOn, aScale);
9934   aCurrentView->AutoZFit();
9935   aCurrentView->Redraw();
9936
9937   return 0;
9938 }
9939
9940 //! Auxiliary function to print projection type
9941 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9942 {
9943   switch (theProjType)
9944   {
9945     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9946     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9947     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9948     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9949     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9950   }
9951   return "UNKNOWN";
9952 }
9953
9954 //===============================================================================================
9955 //function : VCamera
9956 //purpose  :
9957 //===============================================================================================
9958 static int VCamera (Draw_Interpretor& theDI,
9959                     Standard_Integer  theArgsNb,
9960                     const char**      theArgVec)
9961 {
9962   Handle(V3d_View) aView = ViewerTest::CurrentView();
9963   if (aView.IsNull())
9964   {
9965     std::cout << "Error: no active view.\n";
9966     return 1;
9967   }
9968
9969   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9970   if (theArgsNb < 2)
9971   {
9972     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9973     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9974     theDI << "Distance:   " << aCamera->Distance() << "\n";
9975     theDI << "IOD:        " << aCamera->IOD() << "\n";
9976     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9977     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9978     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9979     return 0;
9980   }
9981
9982   TCollection_AsciiString aPrsName;
9983   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9984   {
9985     Standard_CString        anArg = theArgVec[anArgIter];
9986     TCollection_AsciiString anArgCase (anArg);
9987     anArgCase.LowerCase();
9988     if (anArgCase == "-proj"
9989      || anArgCase == "-projection"
9990      || anArgCase == "-projtype"
9991      || anArgCase == "-projectiontype")
9992     {
9993       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9994     }
9995     else if (anArgCase == "-ortho"
9996           || anArgCase == "-orthographic")
9997     {
9998       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
9999     }
10000     else if (anArgCase == "-persp"
10001           || anArgCase == "-perspective"
10002           || anArgCase == "-perspmono"
10003           || anArgCase == "-perspectivemono"
10004           || anArgCase == "-mono")
10005     {
10006       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10007     }
10008     else if (anArgCase == "-stereo"
10009           || anArgCase == "-stereoscopic"
10010           || anArgCase == "-perspstereo"
10011           || anArgCase == "-perspectivestereo")
10012     {
10013       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10014     }
10015     else if (anArgCase == "-left"
10016           || anArgCase == "-lefteye"
10017           || anArgCase == "-monoleft"
10018           || anArgCase == "-monolefteye"
10019           || anArgCase == "-perpsleft"
10020           || anArgCase == "-perpslefteye")
10021     {
10022       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10023     }
10024     else if (anArgCase == "-right"
10025           || anArgCase == "-righteye"
10026           || anArgCase == "-monoright"
10027           || anArgCase == "-monorighteye"
10028           || anArgCase == "-perpsright")
10029     {
10030       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10031     }
10032     else if (anArgCase == "-dist"
10033           || anArgCase == "-distance")
10034     {
10035       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10036       if (anArgValue != NULL
10037       && *anArgValue != '-')
10038       {
10039         ++anArgIter;
10040         aCamera->SetDistance (Draw::Atof (anArgValue));
10041         continue;
10042       }
10043       theDI << aCamera->Distance() << " ";
10044     }
10045     else if (anArgCase == "-iod")
10046     {
10047       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10048       if (anArgValue != NULL
10049       && *anArgValue != '-')
10050       {
10051         ++anArgIter;
10052         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10053         continue;
10054       }
10055       theDI << aCamera->IOD() << " ";
10056     }
10057     else if (anArgCase == "-iodtype")
10058     {
10059       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10060       TCollection_AsciiString anValueCase (anArgValue);
10061       anValueCase.LowerCase();
10062       if (anValueCase == "abs"
10063        || anValueCase == "absolute")
10064       {
10065         ++anArgIter;
10066         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10067         continue;
10068       }
10069       else if (anValueCase == "rel"
10070             || anValueCase == "relative")
10071       {
10072         ++anArgIter;
10073         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10074         continue;
10075       }
10076       else if (*anArgValue != '-')
10077       {
10078         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10079         return 1;
10080       }
10081       switch (aCamera->GetIODType())
10082       {
10083         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10084         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10085       }
10086     }
10087     else if (anArgCase == "-zfocus")
10088     {
10089       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10090       if (anArgValue != NULL
10091       && *anArgValue != '-')
10092       {
10093         ++anArgIter;
10094         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10095         continue;
10096       }
10097       theDI << aCamera->ZFocus() << " ";
10098     }
10099     else if (anArgCase == "-zfocustype")
10100     {
10101       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10102       TCollection_AsciiString anValueCase (anArgValue);
10103       anValueCase.LowerCase();
10104       if (anValueCase == "abs"
10105        || anValueCase == "absolute")
10106       {
10107         ++anArgIter;
10108         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10109         continue;
10110       }
10111       else if (anValueCase == "rel"
10112             || anValueCase == "relative")
10113       {
10114         ++anArgIter;
10115         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10116         continue;
10117       }
10118       else if (*anArgValue != '-')
10119       {
10120         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10121         return 1;
10122       }
10123       switch (aCamera->ZFocusType())
10124       {
10125         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10126         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10127       }
10128     }
10129     else if (anArgCase == "-fov"
10130           || anArgCase == "-fovy")
10131     {
10132       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10133       if (anArgValue != NULL
10134       && *anArgValue != '-')
10135       {
10136         ++anArgIter;
10137         aCamera->SetFOVy (Draw::Atof (anArgValue));
10138         continue;
10139       }
10140       theDI << aCamera->FOVy() << " ";
10141     }
10142     else if (aPrsName.IsEmpty()
10143          && !anArgCase.StartsWith ("-"))
10144     {
10145       aPrsName = anArg;
10146     }
10147     else
10148     {
10149       std::cout << "Error: unknown argument '" << anArg << "'\n";
10150       return 1;
10151     }
10152   }
10153
10154   if (aPrsName.IsEmpty()
10155    || theArgsNb > 2)
10156   {
10157     aView->AutoZFit();
10158     aView->Redraw();
10159   }
10160
10161   if (!aPrsName.IsEmpty())
10162   {
10163     Handle(AIS_CameraFrustum) aCameraFrustum;
10164     if (GetMapOfAIS().IsBound2 (aPrsName))
10165     {
10166       // find existing object
10167       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10168       if (aCameraFrustum.IsNull())
10169       {
10170         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10171         return 1;
10172       }
10173     }
10174
10175     if (aCameraFrustum.IsNull())
10176     {
10177       aCameraFrustum = new AIS_CameraFrustum();
10178     }
10179     else
10180     {
10181       // not include displayed object of old camera frustum in the new one.
10182       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10183       aView->ZFitAll();
10184     }
10185     aCameraFrustum->SetCameraFrustum (aView->Camera());
10186
10187     ViewerTest::Display (aPrsName, aCameraFrustum);
10188   }
10189
10190   return 0;
10191 }
10192
10193 //! Parse stereo output mode
10194 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10195                                          Graphic3d_StereoMode& theMode)
10196 {
10197   TCollection_AsciiString aFlag (theArg);
10198   aFlag.LowerCase();
10199   if (aFlag == "quadbuffer")
10200   {
10201     theMode = Graphic3d_StereoMode_QuadBuffer;
10202   }
10203   else if (aFlag == "anaglyph")
10204   {
10205     theMode = Graphic3d_StereoMode_Anaglyph;
10206   }
10207   else if (aFlag == "row"
10208         || aFlag == "rowinterlaced")
10209   {
10210     theMode = Graphic3d_StereoMode_RowInterlaced;
10211   }
10212   else if (aFlag == "col"
10213         || aFlag == "colinterlaced"
10214         || aFlag == "columninterlaced")
10215   {
10216     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10217   }
10218   else if (aFlag == "chess"
10219         || aFlag == "chessboard")
10220   {
10221     theMode = Graphic3d_StereoMode_ChessBoard;
10222   }
10223   else if (aFlag == "sbs"
10224         || aFlag == "sidebyside")
10225   {
10226     theMode = Graphic3d_StereoMode_SideBySide;
10227   }
10228   else if (aFlag == "ou"
10229         || aFlag == "overunder")
10230   {
10231     theMode = Graphic3d_StereoMode_OverUnder;
10232   }
10233   else if (aFlag == "pageflip"
10234         || aFlag == "softpageflip")
10235   {
10236     theMode = Graphic3d_StereoMode_SoftPageFlip;
10237   }
10238   else
10239   {
10240     return Standard_False;
10241   }
10242   return Standard_True;
10243 }
10244
10245 //! Parse anaglyph filter
10246 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10247                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10248 {
10249   TCollection_AsciiString aFlag (theArg);
10250   aFlag.LowerCase();
10251   if (aFlag == "redcyansimple")
10252   {
10253     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10254   }
10255   else if (aFlag == "redcyan"
10256         || aFlag == "redcyanoptimized")
10257   {
10258     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10259   }
10260   else if (aFlag == "yellowbluesimple")
10261   {
10262     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10263   }
10264   else if (aFlag == "yellowblue"
10265         || aFlag == "yellowblueoptimized")
10266   {
10267     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10268   }
10269   else if (aFlag == "greenmagenta"
10270         || aFlag == "greenmagentasimple")
10271   {
10272     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10273   }
10274   else
10275   {
10276     return Standard_False;
10277   }
10278   return Standard_True;
10279 }
10280
10281 //==============================================================================
10282 //function : VStereo
10283 //purpose  :
10284 //==============================================================================
10285
10286 static int VStereo (Draw_Interpretor& theDI,
10287                     Standard_Integer  theArgNb,
10288                     const char**      theArgVec)
10289 {
10290   Handle(V3d_View) aView = ViewerTest::CurrentView();
10291   if (theArgNb < 2)
10292   {
10293     if (aView.IsNull())
10294     {
10295       std::cout << "Error: no active viewer!\n";
10296       return 0;
10297     }
10298
10299     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10300     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10301     if (isActive)
10302     {
10303       TCollection_AsciiString aMode;
10304       switch (aView->RenderingParams().StereoMode)
10305       {
10306         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10307         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10308         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10309         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10310         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10311         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10312         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10313         case Graphic3d_StereoMode_Anaglyph  :
10314           aMode = "anaglyph";
10315           switch (aView->RenderingParams().AnaglyphFilter)
10316           {
10317             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10318             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10319             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10320             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10321             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10322             default: break;
10323           }
10324         default: break;
10325       }
10326       theDI << "Mode " << aMode << "\n";
10327     }
10328     return 0;
10329   }
10330
10331   Handle(Graphic3d_Camera) aCamera;
10332   Graphic3d_RenderingParams*   aParams   = NULL;
10333   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10334   if (!aView.IsNull())
10335   {
10336     aParams   = &aView->ChangeRenderingParams();
10337     aMode     = aParams->StereoMode;
10338     aCamera   = aView->Camera();
10339   }
10340
10341   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10342   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10343   {
10344     Standard_CString        anArg = theArgVec[anArgIter];
10345     TCollection_AsciiString aFlag (anArg);
10346     aFlag.LowerCase();
10347     if (anUpdateTool.parseRedrawMode (aFlag))
10348     {
10349       continue;
10350     }
10351     else if (aFlag == "0"
10352           || aFlag == "off")
10353     {
10354       if (++anArgIter < theArgNb)
10355       {
10356         std::cout << "Error: wrong number of arguments!\n";
10357         return 1;
10358       }
10359
10360       if (!aCamera.IsNull()
10361        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10362       {
10363         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10364       }
10365       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10366       return 0;
10367     }
10368     else if (aFlag == "1"
10369           || aFlag == "on")
10370     {
10371       if (++anArgIter < theArgNb)
10372       {
10373         std::cout << "Error: wrong number of arguments!\n";
10374         return 1;
10375       }
10376
10377       if (!aCamera.IsNull())
10378       {
10379         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10380       }
10381       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10382       return 0;
10383     }
10384     else if (aFlag == "-reverse"
10385           || aFlag == "-reversed"
10386           || aFlag == "-swap")
10387     {
10388       Standard_Boolean toEnable = Standard_True;
10389       if (++anArgIter < theArgNb
10390       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10391       {
10392         --anArgIter;
10393       }
10394       aParams->ToReverseStereo = toEnable;
10395     }
10396     else if (aFlag == "-noreverse"
10397           || aFlag == "-noswap")
10398     {
10399       Standard_Boolean toDisable = Standard_True;
10400       if (++anArgIter < theArgNb
10401       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10402       {
10403         --anArgIter;
10404       }
10405       aParams->ToReverseStereo = !toDisable;
10406     }
10407     else if (aFlag == "-mode"
10408           || aFlag == "-stereomode")
10409     {
10410       if (++anArgIter >= theArgNb
10411       || !parseStereoMode (theArgVec[anArgIter], aMode))
10412       {
10413         std::cout << "Error: syntax error at '" << anArg << "'\n";
10414         return 1;
10415       }
10416
10417       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10418       {
10419         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10420       }
10421     }
10422     else if (aFlag == "-anaglyph"
10423           || aFlag == "-anaglyphfilter")
10424     {
10425       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10426       if (++anArgIter >= theArgNb
10427       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10428       {
10429         std::cout << "Error: syntax error at '" << anArg << "'\n";
10430         return 1;
10431       }
10432
10433       aMode = Graphic3d_StereoMode_Anaglyph;
10434       aParams->AnaglyphFilter = aFilter;
10435     }
10436     else if (parseStereoMode (anArg, aMode)) // short syntax
10437     {
10438       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10439       {
10440         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10441       }
10442     }
10443     else
10444     {
10445       std::cout << "Error: syntax error at '" << anArg << "'\n";
10446       return 1;
10447     }
10448   }
10449
10450   if (!aView.IsNull())
10451   {
10452     aParams->StereoMode = aMode;
10453     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10454   }
10455   return 0;
10456 }
10457
10458 //===============================================================================================
10459 //function : VDefaults
10460 //purpose  :
10461 //===============================================================================================
10462 static int VDefaults (Draw_Interpretor& theDi,
10463                       Standard_Integer  theArgsNb,
10464                       const char**      theArgVec)
10465 {
10466   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10467   if (aCtx.IsNull())
10468   {
10469     std::cerr << "No active viewer!\n";
10470     return 1;
10471   }
10472
10473   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10474   if (theArgsNb < 2)
10475   {
10476     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10477     {
10478       theDi << "DeflType:           relative\n"
10479             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10480     }
10481     else
10482     {
10483       theDi << "DeflType:           absolute\n"
10484             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10485     }
10486     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10487     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10488     return 0;
10489   }
10490
10491   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10492   {
10493     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10494     anArg.UpperCase();
10495     if (anArg == "-ABSDEFL"
10496      || anArg == "-ABSOLUTEDEFLECTION"
10497      || anArg == "-DEFL"
10498      || anArg == "-DEFLECTION")
10499     {
10500       if (++anArgIter >= theArgsNb)
10501       {
10502         std::cout << "Error: wrong syntax at " << anArg << "\n";
10503         return 1;
10504       }
10505       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10506       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10507     }
10508     else if (anArg == "-RELDEFL"
10509           || anArg == "-RELATIVEDEFLECTION"
10510           || anArg == "-DEVCOEFF"
10511           || anArg == "-DEVIATIONCOEFF"
10512           || anArg == "-DEVIATIONCOEFFICIENT")
10513     {
10514       if (++anArgIter >= theArgsNb)
10515       {
10516         std::cout << "Error: wrong syntax at " << anArg << "\n";
10517         return 1;
10518       }
10519       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10520       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10521     }
10522     else if (anArg == "-ANGDEFL"
10523           || anArg == "-ANGULARDEFL"
10524           || anArg == "-ANGULARDEFLECTION")
10525     {
10526       if (++anArgIter >= theArgsNb)
10527       {
10528         std::cout << "Error: wrong syntax at " << anArg << "\n";
10529         return 1;
10530       }
10531       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10532       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10533     }
10534     else if (anArg == "-AUTOTR"
10535           || anArg == "-AUTOTRIANG"
10536           || anArg == "-AUTOTRIANGULATION")
10537     {
10538       if (++anArgIter >= theArgsNb)
10539       {
10540         std::cout << "Error: wrong syntax at " << anArg << "\n";
10541         return 1;
10542       }
10543       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10544       aValue.LowerCase();
10545       if (aValue == "on"
10546        || aValue == "1")
10547       {
10548         aDefParams->SetAutoTriangulation (Standard_True);
10549       }
10550       else if (aValue == "off"
10551             || aValue == "0")
10552       {
10553         aDefParams->SetAutoTriangulation (Standard_False);
10554       }
10555     }
10556     else
10557     {
10558       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10559     }
10560   }
10561
10562   return 0;
10563 }
10564
10565 //! Auxiliary method
10566 inline void addLight (const Handle(V3d_Light)& theLightNew,
10567                       const Graphic3d_ZLayerId theLayer,
10568                       const Standard_Boolean   theIsGlobal)
10569 {
10570   if (theLightNew.IsNull())
10571   {
10572     return;
10573   }
10574
10575   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10576   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10577   {
10578     aViewer->AddLight (theLightNew);
10579     if (theIsGlobal)
10580     {
10581       aViewer->SetLightOn (theLightNew);
10582     }
10583     else
10584     {
10585       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10586     }
10587   }
10588   else
10589   {
10590     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10591     if (aSettings.Lights().IsNull())
10592     {
10593       aSettings.SetLights (new Graphic3d_LightSet());
10594     }
10595     aSettings.Lights()->Add (theLightNew);
10596     aViewer->SetZLayerSettings (theLayer, aSettings);
10597   }
10598 }
10599
10600 //! Auxiliary method
10601 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10602 {
10603   TCollection_AsciiString anArgNextCase (theArgNext);
10604   anArgNextCase.UpperCase();
10605   if (anArgNextCase.Length() > 5
10606    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10607   {
10608     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10609   }
10610   else
10611   {
10612     return theArgNext.IntegerValue();
10613   }
10614 }
10615
10616 //===============================================================================================
10617 //function : VLight
10618 //purpose  :
10619 //===============================================================================================
10620 static int VLight (Draw_Interpretor& theDi,
10621                    Standard_Integer  theArgsNb,
10622                    const char**      theArgVec)
10623 {
10624   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10625   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10626   if (aView.IsNull()
10627    || aViewer.IsNull())
10628   {
10629     std::cerr << "No active viewer!\n";
10630     return 1;
10631   }
10632
10633   Standard_Real anXYZ[3]   = {};
10634   Standard_Real anAtten[2] = {};
10635   if (theArgsNb < 2)
10636   {
10637     // print lights info
10638     Standard_Integer aLightId = 0;
10639     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10640     {
10641       Handle(V3d_Light) aLight = aLightIter.Value();
10642       const Quantity_Color aColor = aLight->Color();
10643       theDi << "Light #" << aLightId
10644             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10645             << " [" << aLight->GetId() << "]" << "\n";
10646       switch (aLight->Type())
10647       {
10648         case V3d_AMBIENT:
10649         {
10650           theDi << "  Type:       Ambient\n";
10651           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10652           break;
10653         }
10654         case V3d_DIRECTIONAL:
10655         {
10656           theDi << "  Type:       Directional\n";
10657           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10658           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10659           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10660           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10661           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10662           break;
10663         }
10664         case V3d_POSITIONAL:
10665         {
10666           theDi << "  Type:       Positional\n";
10667           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10668           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10669           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10670           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10671           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10672           aLight->Attenuation (anAtten[0], anAtten[1]);
10673           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10674           break;
10675         }
10676         case V3d_SPOT:
10677         {
10678           theDi << "  Type:       Spot\n";
10679           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10680           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10681           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10682           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10683           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10684           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10685           aLight->Attenuation (anAtten[0], anAtten[1]);
10686           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10687           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10688           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10689           break;
10690         }
10691         default:
10692         {
10693           theDi << "  Type:       UNKNOWN\n";
10694           break;
10695         }
10696       }
10697       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10698     }
10699   }
10700
10701   Handle(V3d_Light) aLightNew;
10702   Handle(V3d_Light) aLightOld;
10703   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10704   Standard_Boolean  isGlobal = Standard_True;
10705   Standard_Boolean  toCreate = Standard_False;
10706   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10707   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10708   {
10709     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10710
10711     TCollection_AsciiString aName, aValue;
10712     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10713     TCollection_AsciiString anArgCase (anArg);
10714     anArgCase.UpperCase();
10715     if (anUpdateTool.parseRedrawMode (anArg))
10716     {
10717       continue;
10718     }
10719
10720     if (anArgCase.IsEqual ("NEW")
10721      || anArgCase.IsEqual ("ADD")
10722      || anArgCase.IsEqual ("CREATE")
10723      || anArgCase.IsEqual ("-NEW")
10724      || anArgCase.IsEqual ("-ADD")
10725      || anArgCase.IsEqual ("-CREATE"))
10726     {
10727       toCreate = Standard_True;
10728     }
10729     else if (anArgCase.IsEqual ("-LAYER")
10730           || anArgCase.IsEqual ("-ZLAYER"))
10731     {
10732       if (++anArgIt >= theArgsNb)
10733       {
10734         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10735         return 1;
10736       }
10737
10738       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10739       aValStr.LowerCase();
10740       if (aValStr == "default"
10741        || aValStr == "def")
10742       {
10743         aLayer = Graphic3d_ZLayerId_Default;
10744       }
10745       else if (aValStr == "top")
10746       {
10747         aLayer = Graphic3d_ZLayerId_Top;
10748       }
10749       else if (aValStr == "topmost")
10750       {
10751         aLayer = Graphic3d_ZLayerId_Topmost;
10752       }
10753       else if (aValStr == "toposd"
10754             || aValStr == "osd")
10755       {
10756         aLayer = Graphic3d_ZLayerId_TopOSD;
10757       }
10758       else if (aValStr == "botosd"
10759             || aValStr == "bottom")
10760       {
10761         aLayer = Graphic3d_ZLayerId_BotOSD;
10762       }
10763       else if (aValStr.IsIntegerValue())
10764       {
10765         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10766       }
10767       else
10768       {
10769         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10770         return 1;
10771       }
10772     }
10773     else if (anArgCase.IsEqual ("GLOB")
10774           || anArgCase.IsEqual ("GLOBAL")
10775           || anArgCase.IsEqual ("-GLOB")
10776           || anArgCase.IsEqual ("-GLOBAL"))
10777     {
10778       isGlobal = Standard_True;
10779     }
10780     else if (anArgCase.IsEqual ("LOC")
10781           || anArgCase.IsEqual ("LOCAL")
10782           || anArgCase.IsEqual ("-LOC")
10783           || anArgCase.IsEqual ("-LOCAL"))
10784     {
10785       isGlobal = Standard_False;
10786     }
10787     else if (anArgCase.IsEqual ("DEF")
10788           || anArgCase.IsEqual ("DEFAULTS")
10789           || anArgCase.IsEqual ("-DEF")
10790           || anArgCase.IsEqual ("-DEFAULTS"))
10791     {
10792       toCreate = Standard_False;
10793       aViewer->SetDefaultLights();
10794     }
10795     else if (anArgCase.IsEqual ("CLR")
10796           || anArgCase.IsEqual ("CLEAR")
10797           || anArgCase.IsEqual ("-CLR")
10798           || anArgCase.IsEqual ("-CLEAR"))
10799     {
10800       toCreate = Standard_False;
10801
10802       TColStd_SequenceOfInteger aLayers;
10803       aViewer->GetAllZLayers (aLayers);
10804       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10805       {
10806         if (aLayeriter.Value() == aLayer
10807          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10808         {
10809           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10810           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10811           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10812           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10813           {
10814             break;
10815           }
10816         }
10817       }
10818
10819       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10820       {
10821         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10822         {
10823           Handle(V3d_Light) aLight = aLightIter.Value();
10824           aViewer->DelLight (aLight);
10825           aLightIter = aView->ActiveLightIterator();
10826         }
10827       }
10828     }
10829     else if (anArgCase.IsEqual ("AMB")
10830           || anArgCase.IsEqual ("AMBIENT")
10831           || anArgCase.IsEqual ("AMBLIGHT"))
10832     {
10833       if (!toCreate)
10834       {
10835         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10836         return 1;
10837       }
10838
10839       addLight (aLightNew, aLayer, isGlobal);
10840       toCreate  = Standard_False;
10841       aLightNew = new V3d_AmbientLight();
10842     }
10843     else if (anArgCase.IsEqual ("DIRECTIONAL")
10844           || anArgCase.IsEqual ("DIRLIGHT"))
10845     {
10846       if (!toCreate)
10847       {
10848         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10849         return 1;
10850       }
10851
10852       addLight (aLightNew, aLayer, isGlobal);
10853       toCreate  = Standard_False;
10854       aLightNew = new V3d_DirectionalLight();
10855     }
10856     else if (anArgCase.IsEqual ("SPOT")
10857           || anArgCase.IsEqual ("SPOTLIGHT"))
10858     {
10859       if (!toCreate)
10860       {
10861         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10862         return 1;
10863       }
10864
10865       addLight (aLightNew, aLayer, isGlobal);
10866       toCreate  = Standard_False;
10867       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10868     }
10869     else if (anArgCase.IsEqual ("POSLIGHT")
10870           || anArgCase.IsEqual ("POSITIONAL"))
10871     {
10872       if (!toCreate)
10873       {
10874         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10875         return 1;
10876       }
10877
10878       addLight (aLightNew, aLayer, isGlobal);
10879       toCreate  = Standard_False;
10880       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10881     }
10882     else if (anArgCase.IsEqual ("CHANGE")
10883           || anArgCase.IsEqual ("-CHANGE"))
10884     {
10885       if (++anArgIt >= theArgsNb)
10886       {
10887         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10888         return 1;
10889       }
10890
10891       addLight (aLightNew, aLayer, isGlobal);
10892       aLightNew.Nullify();
10893       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10894       Standard_Integer aLightIt = 0;
10895       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10896       {
10897         if (aLightIt == aLightId)
10898         {
10899           aLightOld = aLightIter.Value();
10900           break;
10901         }
10902       }
10903
10904       if (aLightOld.IsNull())
10905       {
10906         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10907         return 1;
10908       }
10909     }
10910     else if (anArgCase.IsEqual ("DEL")
10911           || anArgCase.IsEqual ("DELETE")
10912           || anArgCase.IsEqual ("-DEL")
10913           || anArgCase.IsEqual ("-DELETE"))
10914     {
10915       Handle(V3d_Light) aLightDel;
10916       if (++anArgIt >= theArgsNb)
10917       {
10918         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10919         return 1;
10920       }
10921
10922       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10923       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10924       Standard_Integer aLightIt = 0;
10925       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10926       {
10927         aLightDel = aLightIter.Value();
10928         if (aLightIt == aLightDelId)
10929         {
10930           break;
10931         }
10932       }
10933       if (aLightDel.IsNull())
10934       {
10935         continue;
10936       }
10937
10938       TColStd_SequenceOfInteger aLayers;
10939       aViewer->GetAllZLayers (aLayers);
10940       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10941       {
10942         if (aLayeriter.Value() == aLayer
10943          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10944         {
10945           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10946           if (!aSettings.Lights().IsNull())
10947           {
10948             aSettings.Lights()->Remove (aLightDel);
10949             if (aSettings.Lights()->IsEmpty())
10950             {
10951               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10952             }
10953           }
10954           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10955           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10956           {
10957             break;
10958           }
10959         }
10960       }
10961
10962       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10963       {
10964         aViewer->DelLight (aLightDel);
10965       }
10966     }
10967     else if (anArgCase.IsEqual ("COLOR")
10968           || anArgCase.IsEqual ("COLOUR")
10969           || anArgCase.IsEqual ("-COLOR")
10970           || anArgCase.IsEqual ("-COLOUR"))
10971     {
10972       if (++anArgIt >= theArgsNb
10973        || aLightCurr.IsNull())
10974       {
10975         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10976         return 1;
10977       }
10978
10979       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10980       anArgNext.UpperCase();
10981       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10982       aLightCurr->SetColor (aColor);
10983     }
10984     else if (anArgCase.IsEqual ("POS")
10985           || anArgCase.IsEqual ("POSITION")
10986           || anArgCase.IsEqual ("-POS")
10987           || anArgCase.IsEqual ("-POSITION"))
10988     {
10989       if ((anArgIt + 3) >= theArgsNb
10990        || aLightCurr.IsNull()
10991        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10992         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10993       {
10994         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10995         return 1;
10996       }
10997
10998       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10999       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11000       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11001       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11002     }
11003     else if (anArgCase.IsEqual ("DIR")
11004           || anArgCase.IsEqual ("DIRECTION")
11005           || anArgCase.IsEqual ("-DIR")
11006           || anArgCase.IsEqual ("-DIRECTION"))
11007     {
11008       if ((anArgIt + 3) >= theArgsNb
11009        || aLightCurr.IsNull()
11010        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11011         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11012       {
11013         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11014         return 1;
11015       }
11016
11017       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11018       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11019       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11020       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11021     }
11022     else if (anArgCase.IsEqual ("SM")
11023           || anArgCase.IsEqual ("SMOOTHNESS")
11024           || anArgCase.IsEqual ("-SM")
11025           || anArgCase.IsEqual ("-SMOOTHNESS"))
11026     {
11027       if (++anArgIt >= theArgsNb
11028        || aLightCurr.IsNull())
11029       {
11030         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11031         return 1;
11032       }
11033
11034       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11035       if (Abs (aSmoothness) <= ShortRealEpsilon())
11036       {
11037         aLightCurr->SetIntensity (1.f);
11038       }
11039       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11040       {
11041         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11042       }
11043       else
11044       {
11045         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11046         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11047       }
11048
11049       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11050       {
11051         aLightCurr->SetSmoothRadius (aSmoothness);
11052       }
11053       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11054       {
11055         aLightCurr->SetSmoothAngle (aSmoothness);
11056       }
11057     }
11058     else if (anArgCase.IsEqual ("INT")
11059           || anArgCase.IsEqual ("INTENSITY")
11060           || anArgCase.IsEqual ("-INT")
11061           || anArgCase.IsEqual ("-INTENSITY"))
11062     {
11063       if (++anArgIt >= theArgsNb
11064        || aLightCurr.IsNull())
11065       {
11066         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11067         return 1;
11068       }
11069
11070       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11071       aLightCurr->SetIntensity (aIntensity);
11072     }
11073     else if (anArgCase.IsEqual ("ANG")
11074           || anArgCase.IsEqual ("ANGLE")
11075           || anArgCase.IsEqual ("-ANG")
11076           || anArgCase.IsEqual ("-ANGLE"))
11077     {
11078       if (++anArgIt >= theArgsNb
11079        || aLightCurr.IsNull()
11080        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11081       {
11082         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11083         return 1;
11084       }
11085
11086       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11087       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11088     }
11089     else if (anArgCase.IsEqual ("CONSTATTEN")
11090           || anArgCase.IsEqual ("CONSTATTENUATION")
11091           || anArgCase.IsEqual ("-CONSTATTEN")
11092           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11093     {
11094       if (++anArgIt >= theArgsNb
11095        || aLightCurr.IsNull()
11096        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11097         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11098       {
11099         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11100         return 1;
11101       }
11102
11103       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11104       anAtten[0] = Atof (theArgVec[anArgIt]);
11105       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11106     }
11107     else if (anArgCase.IsEqual ("LINATTEN")
11108           || anArgCase.IsEqual ("LINEARATTEN")
11109           || anArgCase.IsEqual ("LINEARATTENUATION")
11110           || anArgCase.IsEqual ("-LINATTEN")
11111           || anArgCase.IsEqual ("-LINEARATTEN")
11112           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11113     {
11114       if (++anArgIt >= theArgsNb
11115        || aLightCurr.IsNull()
11116        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11117         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11118       {
11119         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11120         return 1;
11121       }
11122
11123       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11124       anAtten[1] = Atof (theArgVec[anArgIt]);
11125       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11126     }
11127     else if (anArgCase.IsEqual ("EXP")
11128           || anArgCase.IsEqual ("EXPONENT")
11129           || anArgCase.IsEqual ("SPOTEXP")
11130           || anArgCase.IsEqual ("SPOTEXPONENT")
11131           || anArgCase.IsEqual ("-EXP")
11132           || anArgCase.IsEqual ("-EXPONENT")
11133           || anArgCase.IsEqual ("-SPOTEXP")
11134           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11135     {
11136       if (++anArgIt >= theArgsNb
11137        || aLightCurr.IsNull()
11138        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11139       {
11140         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11141         return 1;
11142       }
11143
11144       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11145     }
11146     else if (anArgCase.IsEqual ("HEAD")
11147           || anArgCase.IsEqual ("HEADLIGHT")
11148           || anArgCase.IsEqual ("-HEAD")
11149           || anArgCase.IsEqual ("-HEADLIGHT"))
11150     {
11151       if (aLightCurr.IsNull()
11152        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11153       {
11154         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11155         return 1;
11156       }
11157
11158       Standard_Boolean isHeadLight = Standard_True;
11159       if (anArgIt + 1 < theArgsNb
11160        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11161       {
11162         ++anArgIt;
11163       }
11164       aLightCurr->SetHeadlight (isHeadLight);
11165     }
11166     else
11167     {
11168       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11169     }
11170   }
11171
11172   addLight (aLightNew, aLayer, isGlobal);
11173   return 0;
11174 }
11175
11176 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11177 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11178                                             Standard_Boolean& theToReset,
11179                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11180                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11181 {
11182   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11183   TCollection_AsciiString aVal = theValue;
11184   Standard_Boolean toReverse = Standard_False;
11185   if (aVal == "none")
11186   {
11187     theToReset = Standard_True;
11188     return Standard_True;
11189   }
11190   else if (aVal.StartsWith ("-"))
11191   {
11192     toReverse = Standard_True;
11193     aVal = aVal.SubString (2, aVal.Length());
11194   }
11195   else if (aVal.StartsWith ("no"))
11196   {
11197     toReverse = Standard_True;
11198     aVal = aVal.SubString (3, aVal.Length());
11199   }
11200   else if (aVal.StartsWith ("+"))
11201   {
11202     aVal = aVal.SubString (2, aVal.Length());
11203   }
11204   else
11205   {
11206     theToReset = Standard_True;
11207   }
11208
11209   if (     aVal == "fps"
11210         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11211   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11212   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11213   else if (aVal == "structs"
11214         || aVal == "structures"
11215         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11216   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11217   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11218   else if (aVal == "tris"
11219         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11220   else if (aVal == "pnts"
11221         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11222   else if (aVal == "mem"
11223         || aVal == "gpumem"
11224         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11225   else if (aVal == "skipimmediate"
11226         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11227   else if (aVal == "frametime"
11228         || aVal == "frametimers"
11229         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11230   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11231   else if (aVal == "extended"
11232         || aVal == "verbose"
11233         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11234   else if (aVal == "full"
11235         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11236   else
11237   {
11238     return Standard_False;
11239   }
11240
11241   if (toReverse)
11242   {
11243     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11244   }
11245   else
11246   {
11247     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11248   }
11249   return Standard_True;
11250 }
11251
11252 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11253 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11254                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11255 {
11256   TCollection_AsciiString aValue = theValue;
11257   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11258   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11259   Standard_Boolean toReset = Standard_False;
11260   for (;;)
11261   {
11262     Standard_Integer aSplitPos = aValue.Search ("|");
11263     if (aSplitPos <= 0)
11264     {
11265       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11266       {
11267         return Standard_False;
11268       }
11269       if (toReset)
11270       {
11271         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11272       }
11273       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11274       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11275       return Standard_True;
11276     }
11277
11278     if (aSplitPos > 1)
11279     {
11280       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11281       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11282       {
11283         return Standard_False;
11284       }
11285     }
11286     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11287   }
11288 }
11289
11290 //=======================================================================
11291 //function : VRenderParams
11292 //purpose  : Enables/disables rendering features
11293 //=======================================================================
11294
11295 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11296                                        Standard_Integer  theArgNb,
11297                                        const char**      theArgVec)
11298 {
11299   Handle(V3d_View) aView = ViewerTest::CurrentView();
11300   if (aView.IsNull())
11301   {
11302     std::cerr << "Error: no active viewer!\n";
11303     return 1;
11304   }
11305
11306   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11307   TCollection_AsciiString aCmdName (theArgVec[0]);
11308   aCmdName.LowerCase();
11309   if (aCmdName == "vraytrace")
11310   {
11311     if (theArgNb == 1)
11312     {
11313       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11314       return 0;
11315     }
11316     else if (theArgNb == 2)
11317     {
11318       TCollection_AsciiString aValue (theArgVec[1]);
11319       aValue.LowerCase();
11320       if (aValue == "on"
11321        || aValue == "1")
11322       {
11323         aParams.Method = Graphic3d_RM_RAYTRACING;
11324         aView->Redraw();
11325         return 0;
11326       }
11327       else if (aValue == "off"
11328             || aValue == "0")
11329       {
11330         aParams.Method = Graphic3d_RM_RASTERIZATION;
11331         aView->Redraw();
11332         return 0;
11333       }
11334       else
11335       {
11336         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11337         return 1;
11338       }
11339     }
11340     else
11341     {
11342       std::cout << "Error: wrong number of arguments\n";
11343       return 1;
11344     }
11345   }
11346
11347   if (theArgNb < 2)
11348   {
11349     theDI << "renderMode:  ";
11350     switch (aParams.Method)
11351     {
11352       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11353       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11354     }
11355     theDI << "\n";
11356     theDI << "transparency:  ";
11357     switch (aParams.TransparencyMethod)
11358     {
11359       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11360       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11361                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11362     }
11363     theDI << "\n";
11364     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11365     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11366     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11367     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11368     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11369     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11370     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11371     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11372     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11373     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11374     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11375     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11376     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11377     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11378     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11379     theDI << "shadingModel: ";
11380     switch (aView->ShadingModel())
11381     {
11382       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11383       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11384       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11385       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11386       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11387     }
11388     {
11389       theDI << "perfCounters:";
11390       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11391       {
11392         theDI << " fps";
11393       }
11394       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11395       {
11396         theDI << " cpu";
11397       }
11398       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11399       {
11400         theDI << " structs";
11401       }
11402       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11403       {
11404         theDI << " groups";
11405       }
11406       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11407       {
11408         theDI << " arrays";
11409       }
11410       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11411       {
11412         theDI << " tris";
11413       }
11414       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11415       {
11416         theDI << " pnts";
11417       }
11418       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11419       {
11420         theDI << " gpumem";
11421       }
11422       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11423       {
11424         theDI << " frameTime";
11425       }
11426       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11427       {
11428         theDI << " skipimmediate";
11429       }
11430       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11431       {
11432         theDI << " none";
11433       }
11434       theDI << "\n";
11435     }
11436     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11437     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11438     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11439                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11440                                                                                                                     "noUpdate") << "\n";
11441     theDI << "\n";
11442     return 0;
11443   }
11444
11445   Standard_Boolean toPrint = Standard_False;
11446   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11447   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11448   {
11449     Standard_CString        anArg (theArgVec[anArgIter]);
11450     TCollection_AsciiString aFlag (anArg);
11451     aFlag.LowerCase();
11452     if (anUpdateTool.parseRedrawMode (aFlag))
11453     {
11454       continue;
11455     }
11456     else if (aFlag == "-echo"
11457           || aFlag == "-print")
11458     {
11459       toPrint = Standard_True;
11460       anUpdateTool.Invalidate();
11461     }
11462     else if (aFlag == "-mode"
11463           || aFlag == "-rendermode"
11464           || aFlag == "-render_mode")
11465     {
11466       if (toPrint)
11467       {
11468         switch (aParams.Method)
11469         {
11470           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11471           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11472         }
11473         continue;
11474       }
11475       else
11476       {
11477         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11478         return 1;
11479       }
11480     }
11481     else if (aFlag == "-ray"
11482           || aFlag == "-raytrace")
11483     {
11484       if (toPrint)
11485       {
11486         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11487         continue;
11488       }
11489
11490       aParams.Method = Graphic3d_RM_RAYTRACING;
11491     }
11492     else if (aFlag == "-rast"
11493           || aFlag == "-raster"
11494           || aFlag == "-rasterization")
11495     {
11496       if (toPrint)
11497       {
11498         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11499         continue;
11500       }
11501
11502       aParams.Method = Graphic3d_RM_RASTERIZATION;
11503     }
11504     else if (aFlag == "-msaa")
11505     {
11506       if (toPrint)
11507       {
11508         theDI << aParams.NbMsaaSamples << " ";
11509         continue;
11510       }
11511       else if (++anArgIter >= theArgNb)
11512       {
11513         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11514         return 1;
11515       }
11516
11517       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11518       if (aNbSamples < 0)
11519       {
11520         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11521         return 1;
11522       }
11523       else
11524       {
11525         aParams.NbMsaaSamples = aNbSamples;
11526       }
11527     }
11528     else if (aFlag == "-linefeather"
11529           || aFlag == "-edgefeather"
11530           || aFlag == "-feather")
11531     {
11532       if (toPrint)
11533       {
11534         theDI << " " << aParams.LineFeather << " ";
11535         continue;
11536       }
11537       else if (++anArgIter >= theArgNb)
11538       {
11539         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11540         return 1;
11541       }
11542
11543       TCollection_AsciiString aParam = theArgVec[anArgIter];
11544       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11545       if (aFeather <= 0.0f)
11546       {
11547         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11548         return 1;
11549       }
11550       aParams.LineFeather = aFeather;
11551     }
11552     else if (aFlag == "-oit")
11553     {
11554       if (toPrint)
11555       {
11556         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11557         {
11558           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11559         }
11560         else
11561         {
11562           theDI << "off" << " ";
11563         }
11564         continue;
11565       }
11566       else if (++anArgIter >= theArgNb)
11567       {
11568         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11569         return 1;
11570       }
11571
11572       TCollection_AsciiString aParam = theArgVec[anArgIter];
11573       aParam.LowerCase();
11574       if (aParam.IsRealValue())
11575       {
11576         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11577         if (aWeight < 0.f || aWeight > 1.f)
11578         {
11579           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11580           return 1;
11581         }
11582
11583         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11584         aParams.OitDepthFactor     = aWeight;
11585       }
11586       else if (aParam == "off")
11587       {
11588         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11589       }
11590       else
11591       {
11592         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11593         return 1;
11594       }
11595     }
11596     else if (aFlag == "-depthprepass")
11597     {
11598       if (toPrint)
11599       {
11600         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11601         continue;
11602       }
11603       aParams.ToEnableDepthPrepass = Standard_True;
11604       if (anArgIter + 1 < theArgNb
11605        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11606       {
11607         ++anArgIter;
11608       }
11609     }
11610     else if (aFlag == "-samplealphatocoverage"
11611           || aFlag == "-alphatocoverage")
11612     {
11613       if (toPrint)
11614       {
11615         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11616         continue;
11617       }
11618       aParams.ToEnableAlphaToCoverage = Standard_True;
11619       if (anArgIter + 1 < theArgNb
11620        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11621       {
11622         ++anArgIter;
11623       }
11624     }
11625     else if (aFlag == "-rendscale"
11626           || aFlag == "-renderscale"
11627           || aFlag == "-renderresolutionscale")
11628     {
11629       if (toPrint)
11630       {
11631         theDI << aParams.RenderResolutionScale << " ";
11632         continue;
11633       }
11634       else if (++anArgIter >= theArgNb)
11635       {
11636         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11637         return 1;
11638       }
11639
11640       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11641       if (aScale < 0.01)
11642       {
11643         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11644         return 1;
11645       }
11646       else
11647       {
11648         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11649       }
11650     }
11651     else if (aFlag == "-raydepth"
11652           || aFlag == "-ray_depth")
11653     {
11654       if (toPrint)
11655       {
11656         theDI << aParams.RaytracingDepth << " ";
11657         continue;
11658       }
11659       else if (++anArgIter >= theArgNb)
11660       {
11661         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11662         return 1;
11663       }
11664
11665       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11666
11667       // We allow RaytracingDepth be more than 10 in case of GI enabled
11668       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11669       {
11670         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11671         return 1;
11672       }
11673       else
11674       {
11675         aParams.RaytracingDepth = aDepth;
11676       }
11677     }
11678     else if (aFlag == "-shad"
11679           || aFlag == "-shadows")
11680     {
11681       if (toPrint)
11682       {
11683         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11684         continue;
11685       }
11686
11687       Standard_Boolean toEnable = Standard_True;
11688       if (++anArgIter < theArgNb
11689       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11690       {
11691         --anArgIter;
11692       }
11693       aParams.IsShadowEnabled = toEnable;
11694     }
11695     else if (aFlag == "-refl"
11696           || aFlag == "-reflections")
11697     {
11698       if (toPrint)
11699       {
11700         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11701         continue;
11702       }
11703
11704       Standard_Boolean toEnable = Standard_True;
11705       if (++anArgIter < theArgNb
11706       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11707       {
11708         --anArgIter;
11709       }
11710       aParams.IsReflectionEnabled = toEnable;
11711     }
11712     else if (aFlag == "-fsaa")
11713     {
11714       if (toPrint)
11715       {
11716         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11717         continue;
11718       }
11719
11720       Standard_Boolean toEnable = Standard_True;
11721       if (++anArgIter < theArgNb
11722       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11723       {
11724         --anArgIter;
11725       }
11726       aParams.IsAntialiasingEnabled = toEnable;
11727     }
11728     else if (aFlag == "-gleam")
11729     {
11730       if (toPrint)
11731       {
11732         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11733         continue;
11734       }
11735
11736       Standard_Boolean toEnable = Standard_True;
11737       if (++anArgIter < theArgNb
11738       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11739       {
11740         --anArgIter;
11741       }
11742       aParams.IsTransparentShadowEnabled = toEnable;
11743     }
11744     else if (aFlag == "-gi")
11745     {
11746       if (toPrint)
11747       {
11748         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11749         continue;
11750       }
11751
11752       Standard_Boolean toEnable = Standard_True;
11753       if (++anArgIter < theArgNb
11754       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11755       {
11756         --anArgIter;
11757       }
11758       aParams.IsGlobalIlluminationEnabled = toEnable;
11759       if (!toEnable)
11760       {
11761         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11762       }
11763     }
11764     else if (aFlag == "-blockedrng"
11765           || aFlag == "-brng")
11766     {
11767       if (toPrint)
11768       {
11769         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11770         continue;
11771       }
11772
11773       Standard_Boolean toEnable = Standard_True;
11774       if (++anArgIter < theArgNb
11775         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11776       {
11777         --anArgIter;
11778       }
11779       aParams.CoherentPathTracingMode = toEnable;
11780     }
11781     else if (aFlag == "-maxrad")
11782     {
11783       if (toPrint)
11784       {
11785         theDI << aParams.RadianceClampingValue << " ";
11786         continue;
11787       }
11788       else if (++anArgIter >= theArgNb)
11789       {
11790         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11791         return 1;
11792       }
11793
11794       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11795       if (!aMaxRadStr.IsRealValue())
11796       {
11797         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11798         return 1;
11799       }
11800
11801       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11802       if (aMaxRadiance <= 0.0)
11803       {
11804         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11805         return 1;
11806       }
11807       else
11808       {
11809         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11810       }
11811     }
11812     else if (aFlag == "-iss")
11813     {
11814       if (toPrint)
11815       {
11816         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11817         continue;
11818       }
11819
11820       Standard_Boolean toEnable = Standard_True;
11821       if (++anArgIter < theArgNb
11822         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11823       {
11824         --anArgIter;
11825       }
11826       aParams.AdaptiveScreenSampling = toEnable;
11827     }
11828     else if (aFlag == "-issatomic")
11829     {
11830       if (toPrint)
11831       {
11832         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11833         continue;
11834       }
11835
11836       Standard_Boolean toEnable = Standard_True;
11837       if (++anArgIter < theArgNb
11838       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11839       {
11840         --anArgIter;
11841       }
11842       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11843     }
11844     else if (aFlag == "-issd")
11845     {
11846       if (toPrint)
11847       {
11848         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11849         continue;
11850       }
11851
11852       Standard_Boolean toEnable = Standard_True;
11853       if (++anArgIter < theArgNb
11854         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11855       {
11856         --anArgIter;
11857       }
11858       aParams.ShowSamplingTiles = toEnable;
11859     }
11860     else if (aFlag == "-tilesize")
11861     {
11862       if (toPrint)
11863       {
11864         theDI << aParams.RayTracingTileSize << " ";
11865         continue;
11866       }
11867       else if (++anArgIter >= theArgNb)
11868       {
11869         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11870         return 1;
11871       }
11872
11873       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11874       if (aTileSize < 1)
11875       {
11876         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11877         return 1;
11878       }
11879       aParams.RayTracingTileSize = aTileSize;
11880     }
11881     else if (aFlag == "-nbtiles")
11882     {
11883       if (toPrint)
11884       {
11885         theDI << aParams.NbRayTracingTiles << " ";
11886         continue;
11887       }
11888       else if (++anArgIter >= theArgNb)
11889       {
11890         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11891         return 1;
11892       }
11893
11894       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11895       if (aNbTiles < -1)
11896       {
11897         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11898         return 1;
11899       }
11900       else if (aNbTiles > 0
11901             && (aNbTiles < 64
11902              || aNbTiles > 1024))
11903       {
11904         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11905       }
11906       aParams.NbRayTracingTiles = aNbTiles;
11907     }
11908     else if (aFlag == "-env")
11909     {
11910       if (toPrint)
11911       {
11912         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11913         continue;
11914       }
11915
11916       Standard_Boolean toEnable = Standard_True;
11917       if (++anArgIter < theArgNb
11918         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11919       {
11920         --anArgIter;
11921       }
11922       aParams.UseEnvironmentMapBackground = toEnable;
11923     }
11924     else if (aFlag == "-twoside")
11925     {
11926       if (toPrint)
11927       {
11928         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11929         continue;
11930       }
11931
11932       Standard_Boolean toEnable = Standard_True;
11933       if (++anArgIter < theArgNb
11934         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11935       {
11936         --anArgIter;
11937       }
11938       aParams.TwoSidedBsdfModels = toEnable;
11939     }
11940     else if (aFlag == "-shademodel"
11941           || aFlag == "-shadingmodel"
11942           || aFlag == "-shading")
11943     {
11944       if (toPrint)
11945       {
11946         switch (aView->ShadingModel())
11947         {
11948           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11949           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11950           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11951           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11952           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11953         }
11954         continue;
11955       }
11956
11957       if (++anArgIter >= theArgNb)
11958       {
11959         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11960       }
11961
11962       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11963       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11964        && aModel != Graphic3d_TOSM_DEFAULT)
11965       {
11966         aView->SetShadingModel (aModel);
11967       }
11968       else
11969       {
11970         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11971         return 1;
11972       }
11973     }
11974     else if (aFlag == "-resolution")
11975     {
11976       if (++anArgIter >= theArgNb)
11977       {
11978         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11979         return 1;
11980       }
11981
11982       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11983       if (aResolution.IsIntegerValue())
11984       {
11985         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11986       }
11987       else
11988       {
11989         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11990         return 1;
11991       }
11992     }
11993     else if (aFlag == "-rebuildglsl"
11994           || aFlag == "-rebuild")
11995     {
11996       if (toPrint)
11997       {
11998         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11999         continue;
12000       }
12001
12002       Standard_Boolean toEnable = Standard_True;
12003       if (++anArgIter < theArgNb
12004           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12005       {
12006         --anArgIter;
12007       }
12008       aParams.RebuildRayTracingShaders = toEnable;
12009     }
12010     else if (aFlag == "-focal")
12011     {
12012       if (++anArgIter >= theArgNb)
12013       {
12014         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12015         return 1;
12016       }
12017
12018       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12019       if (aParam.IsRealValue())
12020       {
12021         float aFocalDist = static_cast<float> (aParam.RealValue());
12022         if (aFocalDist < 0)
12023         {
12024           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12025           return 1;
12026         }
12027         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12028       }
12029       else
12030       {
12031         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12032         return 1;
12033       }
12034     }
12035     else if (aFlag == "-aperture")
12036     {
12037       if (++anArgIter >= theArgNb)
12038       {
12039         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12040         return 1;
12041       }
12042
12043       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12044       if (aParam.IsRealValue())
12045       {
12046         float aApertureSize = static_cast<float> (aParam.RealValue());
12047         if (aApertureSize < 0)
12048         {
12049           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12050           return 1;
12051         }
12052         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12053       }
12054       else
12055       {
12056         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12057         return 1;
12058       }
12059     }
12060     else if (aFlag == "-exposure")
12061     {
12062       if (++anArgIter >= theArgNb)
12063       {
12064         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12065         return 1;
12066       }
12067
12068       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12069       if (anExposure.IsRealValue())
12070       {
12071         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12072       }
12073       else
12074       {
12075         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12076         return 1;
12077       }
12078     }
12079     else if (aFlag == "-whitepoint")
12080     {
12081       if (++anArgIter >= theArgNb)
12082       {
12083         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12084         return 1;
12085       }
12086
12087       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12088       if (aWhitePoint.IsRealValue())
12089       {
12090         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12091       }
12092       else
12093       {
12094         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12095         return 1;
12096       }
12097     }
12098     else if (aFlag == "-tonemapping")
12099     {
12100       if (++anArgIter >= theArgNb)
12101       {
12102         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12103         return 1;
12104       }
12105
12106       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12107       aMode.LowerCase();
12108
12109       if (aMode == "disabled")
12110       {
12111         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12112       }
12113       else if (aMode == "filmic")
12114       {
12115         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12116       }
12117       else
12118       {
12119         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12120         return 1;
12121       }
12122     }
12123     else if (aFlag == "-performancestats"
12124           || aFlag == "-performancecounters"
12125           || aFlag == "-perfstats"
12126           || aFlag == "-perfcounters"
12127           || aFlag == "-stats")
12128     {
12129       if (++anArgIter >= theArgNb)
12130       {
12131         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12132         return 1;
12133       }
12134
12135       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12136       aFlagsStr.LowerCase();
12137       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12138       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12139       {
12140         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12141         return 1;
12142       }
12143       aView->ChangeRenderingParams().CollectedStats = aFlags;
12144       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12145     }
12146     else if (aFlag == "-perfupdateinterval"
12147           || aFlag == "-statsupdateinterval")
12148     {
12149       if (++anArgIter >= theArgNb)
12150       {
12151         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12152         return 1;
12153       }
12154       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12155     }
12156     else if (aFlag == "-perfchart"
12157           || aFlag == "-statschart")
12158     {
12159       if (++anArgIter >= theArgNb)
12160       {
12161         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12162         return 1;
12163       }
12164       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12165     }
12166     else if (aFlag == "-perfchartmax"
12167           || aFlag == "-statschartmax")
12168     {
12169       if (++anArgIter >= theArgNb)
12170       {
12171         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12172         return 1;
12173       }
12174       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12175     }
12176     else if (aFlag == "-frustumculling"
12177           || aFlag == "-culling")
12178     {
12179       if (toPrint)
12180       {
12181         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12182                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12183                                                                                                    "noUpdate") << " ";
12184         continue;
12185       }
12186
12187       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12188       if (++anArgIter < theArgNb)
12189       {
12190         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12191         aStateStr.LowerCase();
12192         bool toEnable = true;
12193         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12194         {
12195           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12196         }
12197         else if (aStateStr == "noupdate"
12198               || aStateStr == "freeze")
12199         {
12200           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12201         }
12202         else
12203         {
12204           --anArgIter;
12205         }
12206       }
12207       aParams.FrustumCullingState = aState;
12208     }
12209     else
12210     {
12211       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12212       return 1;
12213     }
12214   }
12215
12216   return 0;
12217 }
12218
12219 //=======================================================================
12220 //function : searchInfo
12221 //purpose  :
12222 //=======================================================================
12223 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12224                                            const TCollection_AsciiString&              theKey)
12225 {
12226   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12227   {
12228     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12229     {
12230       return anIter.Value();
12231     }
12232   }
12233   return TCollection_AsciiString();
12234 }
12235
12236 //=======================================================================
12237 //function : VStatProfiler
12238 //purpose  :
12239 //=======================================================================
12240 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12241                                        Standard_Integer  theArgNb,
12242                                        const char**      theArgVec)
12243 {
12244   Handle(V3d_View) aView = ViewerTest::CurrentView();
12245   if (aView.IsNull())
12246   {
12247     std::cerr << "Error: no active viewer!\n";
12248     return 1;
12249   }
12250
12251   Standard_Boolean toRedraw = Standard_True;
12252   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12253   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12254   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12255   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12256   {
12257     Standard_CString        anArg (theArgVec[anArgIter]);
12258     TCollection_AsciiString aFlag (anArg);
12259     aFlag.LowerCase();
12260     if (aFlag == "-noredraw")
12261     {
12262       toRedraw = Standard_False;
12263     }
12264     else
12265     {
12266       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12267       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12268       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12269       else if (aFlag == "alllayers"
12270             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12271       else if (aFlag == "allstructs"
12272             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12273       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12274       else if (aFlag == "allarrays"
12275             || aFlag == "fillarrays"
12276             || aFlag == "linearrays"
12277             || aFlag == "pointarrays"
12278             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12279       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12280       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12281       else if (aFlag == "geommem"
12282             || aFlag == "texturemem"
12283             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12284       else if (aFlag == "elapsedframe"
12285             || aFlag == "cpuframeaverage"
12286             || aFlag == "cpupickingaverage"
12287             || aFlag == "cpucullingaverage"
12288             || aFlag == "cpudynaverage"
12289             || aFlag == "cpuframemax"
12290             || aFlag == "cpupickingmax"
12291             || aFlag == "cpucullingmax"
12292             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12293       else
12294       {
12295         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12296         continue;
12297       }
12298
12299       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12300     }
12301   }
12302
12303   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12304   {
12305     aView->ChangeRenderingParams().CollectedStats =
12306       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12307
12308     if (toRedraw)
12309     {
12310       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12311       aView->Redraw();
12312       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12313     }
12314
12315     TColStd_IndexedDataMapOfStringString aDict;
12316     aView->StatisticInformation (aDict);
12317
12318     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12319
12320     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12321     {
12322       Standard_CString        anArg(theArgVec[anArgIter]);
12323       TCollection_AsciiString aFlag(anArg);
12324       aFlag.LowerCase();
12325       if (aFlag == "fps")
12326       {
12327         theDI << searchInfo (aDict, "FPS") << " ";
12328       }
12329       else if (aFlag == "cpu")
12330       {
12331         theDI << searchInfo (aDict, "CPU FPS") << " ";
12332       }
12333       else if (aFlag == "alllayers")
12334       {
12335         theDI << searchInfo (aDict, "Layers") << " ";
12336       }
12337       else if (aFlag == "layers")
12338       {
12339         theDI << searchInfo (aDict, "Rendered layers") << " ";
12340       }
12341       else if (aFlag == "allstructs")
12342       {
12343         theDI << searchInfo (aDict, "Structs") << " ";
12344       }
12345       else if (aFlag == "structs")
12346       {
12347         theDI << searchInfo (aDict, "Rendered structs") << " ";
12348       }
12349       else if (aFlag == "groups")
12350       {
12351         theDI << searchInfo (aDict, "Rendered groups") << " ";
12352       }
12353       else if (aFlag == "allarrays")
12354       {
12355         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12356       }
12357       else if (aFlag == "fillarrays")
12358       {
12359         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12360       }
12361       else if (aFlag == "linearrays")
12362       {
12363         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12364       }
12365       else if (aFlag == "pointarrays")
12366       {
12367         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12368       }
12369       else if (aFlag == "textarrays")
12370       {
12371         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12372       }
12373       else if (aFlag == "triangles")
12374       {
12375         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12376       }
12377       else if (aFlag == "points")
12378       {
12379         theDI << searchInfo (aDict, "Rendered points") << " ";
12380       }
12381       else if (aFlag == "geommem")
12382       {
12383         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12384       }
12385       else if (aFlag == "texturemem")
12386       {
12387         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12388       }
12389       else if (aFlag == "framemem")
12390       {
12391         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12392       }
12393       else if (aFlag == "elapsedframe")
12394       {
12395         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12396       }
12397       else if (aFlag == "cpuframe_average")
12398       {
12399         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12400       }
12401       else if (aFlag == "cpupicking_average")
12402       {
12403         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12404       }
12405       else if (aFlag == "cpuculling_average")
12406       {
12407         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12408       }
12409       else if (aFlag == "cpudyn_average")
12410       {
12411         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12412       }
12413       else if (aFlag == "cpuframe_max")
12414       {
12415         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12416       }
12417       else if (aFlag == "cpupicking_max")
12418       {
12419         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12420       }
12421       else if (aFlag == "cpuculling_max")
12422       {
12423         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12424       }
12425       else if (aFlag == "cpudyn_max")
12426       {
12427         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12428       }
12429     }
12430   }
12431   else
12432   {
12433     if (toRedraw)
12434     {
12435       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12436       aView->Redraw();
12437       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12438     }
12439     theDI << "Statistic info:\n" << aView->StatisticInformation();
12440   }
12441   return 0;
12442 }
12443
12444 //=======================================================================
12445 //function : VXRotate
12446 //purpose  :
12447 //=======================================================================
12448 static Standard_Integer VXRotate (Draw_Interpretor& di,
12449                                    Standard_Integer argc,
12450                                    const char ** argv)
12451 {
12452   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12453   if (aContext.IsNull())
12454   {
12455     di << argv[0] << "ERROR : use 'vinit' command before \n";
12456     return 1;
12457   }
12458
12459   if (argc != 3)
12460   {
12461     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12462     return 1;
12463   }
12464
12465   TCollection_AsciiString aName (argv[1]);
12466   Standard_Real anAngle = Draw::Atof (argv[2]);
12467
12468   // find object
12469   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12470   Handle(AIS_InteractiveObject) anIObj;
12471   if (!aMap.Find2 (aName, anIObj))
12472   {
12473     di << "Use 'vdisplay' before\n";
12474     return 1;
12475   }
12476
12477   gp_Trsf aTransform;
12478   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12479   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12480
12481   aContext->SetLocation (anIObj, aTransform);
12482   aContext->UpdateCurrentViewer();
12483   return 0;
12484 }
12485
12486 //===============================================================================================
12487 //class   : ViewerTest_AISManipulator
12488 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12489 //===============================================================================================
12490 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12491
12492 class ViewerTest_AISManipulator : public AIS_Manipulator
12493 {
12494 public:
12495
12496   ViewerTest_AISManipulator() : AIS_Manipulator()
12497   {
12498     GetMapOfAISManipulators().Add (this);
12499   }
12500
12501   virtual ~ViewerTest_AISManipulator()
12502   {
12503     GetMapOfAISManipulators().Remove (this);
12504   }
12505
12506   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12507 };
12508
12509 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12510 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12511
12512 //===============================================================================================
12513 //function : VManipulator
12514 //purpose  :
12515 //===============================================================================================
12516 static int VManipulator (Draw_Interpretor& theDi,
12517                          Standard_Integer  theArgsNb,
12518                          const char**      theArgVec)
12519 {
12520   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12521   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12522   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12523   if (aCurrentView.IsNull()
12524    || aViewer.IsNull())
12525   {
12526     std::cerr << "No active viewer!\n";
12527     return 1;
12528   }
12529
12530   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12531   Standard_Integer anArgIter = 1;
12532   for (; anArgIter < theArgsNb; ++anArgIter)
12533   {
12534     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12535   }
12536
12537   ViewerTest_CmdParser aCmd;
12538   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12539   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12540   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12541   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12542   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12543   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12544   aCmd.AddOption ("detach",         "...       - detach manipulator");
12545
12546   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12547   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12548   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12549
12550   aCmd.AddOption ("move",   "... x y z - move object");
12551   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12552   aCmd.AddOption ("scale",  "... factor - scale object");
12553
12554   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12555   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12556   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12557   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12558   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12559   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12560   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12561   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12562   aCmd.AddOption ("size",              "... size - set size of manipulator");
12563   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12564
12565   aCmd.Parse (theArgsNb, theArgVec);
12566
12567   if (aCmd.HasOption ("help"))
12568   {
12569     theDi.PrintHelp (theArgVec[0]);
12570     return 0;
12571   }
12572
12573   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12574
12575   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12576
12577   if (aName.IsEmpty())
12578   {
12579     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12580     return 1;
12581   }
12582
12583   // ----------------------------------
12584   // detach existing manipulator object
12585   // ----------------------------------
12586
12587   if (aCmd.HasOption ("detach"))
12588   {
12589     if (!aMapAIS.IsBound2 (aName))
12590     {
12591       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12592       return 1;
12593     }
12594
12595     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12596     if (aManipulator.IsNull())
12597     {
12598       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12599       return 1;
12600     }
12601
12602     aManipulator->Detach();
12603     aMapAIS.UnBind2 (aName);
12604     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12605
12606     return 0;
12607   }
12608
12609   // -----------------------------------------------
12610   // find or create manipulator if it does not exist
12611   // -----------------------------------------------
12612
12613   Handle(AIS_Manipulator) aManipulator;
12614   if (!aMapAIS.IsBound2 (aName))
12615   {
12616     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12617
12618     aManipulator = new ViewerTest_AISManipulator();
12619     aManipulator->SetModeActivationOnDetection (true);
12620     aMapAIS.Bind (aManipulator, aName);
12621   }
12622   else
12623   {
12624     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12625     if (aManipulator.IsNull())
12626     {
12627       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12628       return 1;
12629     }
12630   }
12631
12632   // -----------------------------------------
12633   // change properties of manipulator instance
12634   // -----------------------------------------
12635
12636   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12637   {
12638     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12639   }
12640   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12641   {
12642     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12643   }
12644   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12645   {
12646     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12647   }
12648   if (aCmd.HasOption("followDragging", 1, Standard_True))
12649   {
12650     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12651   }
12652   if (aCmd.HasOption ("gap", 1, Standard_True))
12653   {
12654     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12655   }
12656   if (aCmd.HasOption ("part", 3, Standard_True))
12657   {
12658     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12659     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12660     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12661     if (aMode < 1 || aMode > 4)
12662     {
12663       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12664       return 1;
12665     }
12666
12667     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12668   }
12669   if (aCmd.HasOption("parts", 2, Standard_True))
12670   {
12671     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12672     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12673     if (aMode < 1 || aMode > 4)
12674     {
12675       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12676       return 1;
12677     }
12678
12679     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12680   }
12681   if (aCmd.HasOption ("pos", 3, Standard_True))
12682   {
12683     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12684     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12685     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12686
12687     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12688   }
12689   if (aCmd.HasOption ("size", 1, Standard_True))
12690   {
12691     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12692   }
12693   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12694   {
12695     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12696
12697     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12698     {
12699       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12700       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12701     }
12702   }
12703
12704   // ---------------------------------------------------
12705   // attach, detach or access manipulator from an object
12706   // ---------------------------------------------------
12707
12708   if (aCmd.HasOption ("attach"))
12709   {
12710     // Find an object and attach manipulator to it
12711     if (!aCmd.HasOption ("attach", 1, Standard_True))
12712     {
12713       return 1;
12714     }
12715
12716     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12717     Handle(AIS_InteractiveObject) anObject;
12718     if (!aMapAIS.Find2 (anObjName, anObject))
12719     {
12720       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12721       return 1;
12722     }
12723
12724     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12725     {
12726       if (anIt.Value()->IsAttached()
12727        && anIt.Value()->Object() == anObject)
12728       {
12729         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12730         return 1;
12731       }
12732     }
12733
12734     AIS_Manipulator::OptionsForAttach anOptions;
12735     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12736     {
12737       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12738     }
12739     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12740     {
12741       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12742     }
12743     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12744     {
12745       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12746     }
12747
12748     aManipulator->Attach (anObject, anOptions);
12749
12750     // Check view option
12751     if (aCmd.HasOption ("view"))
12752     {
12753       if (!aCmd.HasOption ("view", 1, Standard_True))
12754       {
12755         return 1;
12756       }
12757       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12758       Handle(V3d_View) aView;
12759       if (aViewString.IsEqual ("active"))
12760       {
12761         aView = ViewerTest::CurrentView();
12762       }
12763       else // Check view name
12764       {
12765         ViewerTest_Names aViewNames (aViewString);
12766         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12767         {
12768           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12769           return 1;
12770         }
12771         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12772         if (aView.IsNull())
12773         {
12774           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12775           return 1;
12776         }
12777       }
12778       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12779         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12780       {
12781         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12782       }
12783       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12784     }
12785   }
12786
12787   // --------------------------------------
12788   // apply transformation using manipulator
12789   // --------------------------------------
12790
12791   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12792   {
12793     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12794   }
12795   if (aCmd.HasOption ("transform", 2, Standard_True))
12796   {
12797     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12798   }
12799   if (aCmd.HasOption ("stopTransform"))
12800   {
12801     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12802
12803     aManipulator->StopTransform (toApply);
12804   }
12805
12806   gp_Trsf aT;
12807   if (aCmd.HasOption ("move", 3, Standard_True))
12808   {
12809     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12810   }
12811   if (aCmd.HasOption ("rotate", 7, Standard_True))
12812   {
12813     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12814   }
12815   if (aCmd.HasOption ("scale", 1))
12816   {
12817     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12818   }
12819
12820   if (aT.Form() != gp_Identity)
12821   {
12822     aManipulator->Transform (aT);
12823   }
12824
12825   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12826
12827   return 0;
12828 }
12829
12830 //===============================================================================================
12831 //function : VSelectionProperties
12832 //purpose  :
12833 //===============================================================================================
12834 static int VSelectionProperties (Draw_Interpretor& theDi,
12835                                  Standard_Integer  theArgsNb,
12836                                  const char**      theArgVec)
12837 {
12838   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12839   if (aCtx.IsNull())
12840   {
12841     std::cerr << "No active viewer!\n";
12842     return 1;
12843   }
12844
12845   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12846   {
12847     // handle obsolete alias
12848     bool toEnable = true;
12849     if (theArgsNb < 2)
12850     {
12851       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12852       return 0;
12853     }
12854     else if (theArgsNb != 2
12855          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12856     {
12857       std::cout << "Syntax error: wrong number of parameters.";
12858       return 1;
12859     }
12860     if (toEnable != aCtx->ToHilightSelected())
12861     {
12862       aCtx->ClearDetected();
12863       aCtx->SetToHilightSelected (toEnable);
12864     }
12865     return 0;
12866   }
12867
12868   Standard_Boolean toPrint  = theArgsNb == 1;
12869   Standard_Boolean toRedraw = Standard_False;
12870   Standard_Integer anArgIter = 1;
12871   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12872   if (anArgIter < theArgsNb)
12873   {
12874     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12875     anArgFirst.LowerCase();
12876     ++anArgIter;
12877     if (anArgFirst == "dynhighlight"
12878      || anArgFirst == "dynhilight"
12879      || anArgFirst == "dynamichighlight"
12880      || anArgFirst == "dynamichilight")
12881     {
12882       aType = Prs3d_TypeOfHighlight_Dynamic;
12883     }
12884     else if (anArgFirst == "localdynhighlight"
12885           || anArgFirst == "localdynhilight"
12886           || anArgFirst == "localdynamichighlight"
12887           || anArgFirst == "localdynamichilight")
12888     {
12889       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12890     }
12891     else if (anArgFirst == "selhighlight"
12892           || anArgFirst == "selhilight"
12893           || anArgFirst == "selectedhighlight"
12894           || anArgFirst == "selectedhilight")
12895     {
12896       aType = Prs3d_TypeOfHighlight_Selected;
12897     }
12898     else if (anArgFirst == "localselhighlight"
12899           || anArgFirst == "localselhilight"
12900           || anArgFirst == "localselectedhighlight"
12901           || anArgFirst == "localselectedhilight")
12902     {
12903       aType = Prs3d_TypeOfHighlight_LocalSelected;
12904     }
12905     else
12906     {
12907       --anArgIter;
12908     }
12909   }
12910   for (; anArgIter < theArgsNb; ++anArgIter)
12911   {
12912     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12913     anArg.LowerCase();
12914     if (anArg == "-help")
12915     {
12916       theDi.PrintHelp (theArgVec[0]);
12917       return 0;
12918     }
12919     else if (anArg == "-print")
12920     {
12921       toPrint = Standard_True;
12922     }
12923     else if (anArg == "-autoactivate")
12924     {
12925       Standard_Boolean toEnable = Standard_True;
12926       if (anArgIter + 1 < theArgsNb
12927        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12928       {
12929         ++anArgIter;
12930       }
12931       aCtx->SetAutoActivateSelection (toEnable);
12932     }
12933     else if (anArg == "-automatichighlight"
12934           || anArg == "-automatichilight"
12935           || anArg == "-autohighlight"
12936           || anArg == "-autohilight")
12937     {
12938       Standard_Boolean toEnable = Standard_True;
12939       if (anArgIter + 1 < theArgsNb
12940        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12941       {
12942         ++anArgIter;
12943       }
12944       aCtx->ClearSelected (false);
12945       aCtx->ClearDetected();
12946       aCtx->SetAutomaticHilight (toEnable);
12947       toRedraw = true;
12948     }
12949     else if (anArg == "-highlightselected"
12950           || anArg == "-hilightselected")
12951     {
12952       Standard_Boolean toEnable = Standard_True;
12953       if (anArgIter + 1 < theArgsNb
12954        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12955       {
12956         ++anArgIter;
12957       }
12958       aCtx->ClearDetected();
12959       aCtx->SetToHilightSelected (toEnable);
12960       toRedraw = true;
12961     }
12962     else if (anArg == "-pickstrategy"
12963           || anArg == "-pickingstrategy")
12964     {
12965       if (++anArgIter >= theArgsNb)
12966       {
12967         std::cout << "Syntax error: type of highlighting is undefined\n";
12968         return 1;
12969       }
12970
12971       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12972       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12973       aVal.LowerCase();
12974       if (aVal == "first"
12975        || aVal == "firstaccepted"
12976        || aVal == "firstacceptable")
12977       {
12978         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12979       }
12980       else if (aVal == "topmost"
12981             || aVal == "onlyTopmost")
12982       {
12983         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12984       }
12985       else
12986       {
12987         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12988         return 1;
12989       }
12990
12991       aCtx->SetPickingStrategy (aStrategy);
12992     }
12993     else if (anArg == "-pixtol"
12994           && anArgIter + 1 < theArgsNb)
12995     {
12996       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12997     }
12998     else if ((anArg == "-mode"
12999            || anArg == "-dispmode")
13000           && anArgIter + 1 < theArgsNb)
13001     {
13002       if (aType == Prs3d_TypeOfHighlight_None)
13003       {
13004         std::cout << "Syntax error: type of highlighting is undefined\n";
13005         return 1;
13006       }
13007
13008       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13009       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13010       aStyle->SetDisplayMode (aDispMode);
13011       toRedraw = Standard_True;
13012     }
13013     else if (anArg == "-layer"
13014           && anArgIter + 1 < theArgsNb)
13015     {
13016       if (aType == Prs3d_TypeOfHighlight_None)
13017       {
13018         std::cout << "Syntax error: type of highlighting is undefined\n";
13019         return 1;
13020       }
13021
13022       ++anArgIter;
13023       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13024       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13025       {
13026         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13027         return 1;
13028       }
13029
13030       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13031       aStyle->SetZLayer (aNewLayer);
13032       toRedraw = Standard_True;
13033     }
13034     else if (anArg == "-hicolor"
13035           || anArg == "-selcolor"
13036           || anArg == "-color")
13037     {
13038       if (anArg.StartsWith ("-hi"))
13039       {
13040         aType = Prs3d_TypeOfHighlight_Dynamic;
13041       }
13042       else if (anArg.StartsWith ("-sel"))
13043       {
13044         aType = Prs3d_TypeOfHighlight_Selected;
13045       }
13046       else if (aType == Prs3d_TypeOfHighlight_None)
13047       {
13048         std::cout << "Syntax error: type of highlighting is undefined\n";
13049         return 1;
13050       }
13051
13052       Quantity_Color aColor;
13053       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13054                                                            theArgVec + anArgIter + 1,
13055                                                            aColor);
13056       if (aNbParsed == 0)
13057       {
13058         std::cout << "Syntax error: need more arguments.\n";
13059         return 1;
13060       }
13061       anArgIter += aNbParsed;
13062
13063       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13064       aStyle->SetColor (aColor);
13065       toRedraw = Standard_True;
13066     }
13067     else if ((anArg == "-transp"
13068            || anArg == "-transparency"
13069            || anArg == "-hitransp"
13070            || anArg == "-seltransp"
13071            || anArg == "-hitransplocal"
13072            || anArg == "-seltransplocal")
13073           && anArgIter + 1 < theArgsNb)
13074     {
13075       if (anArg.StartsWith ("-hi"))
13076       {
13077         aType = Prs3d_TypeOfHighlight_Dynamic;
13078       }
13079       else if (anArg.StartsWith ("-sel"))
13080       {
13081         aType = Prs3d_TypeOfHighlight_Selected;
13082       }
13083       else if (aType == Prs3d_TypeOfHighlight_None)
13084       {
13085         std::cout << "Syntax error: type of highlighting is undefined\n";
13086         return 1;
13087       }
13088
13089       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13090       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13091       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13092       toRedraw = Standard_True;
13093     }
13094     else if ((anArg == "-mat"
13095            || anArg == "-material")
13096           && anArgIter + 1 < theArgsNb)
13097     {
13098       if (aType == Prs3d_TypeOfHighlight_None)
13099       {
13100         std::cout << "Syntax error: type of highlighting is undefined\n";
13101         return 1;
13102       }
13103
13104       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13105       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13106       if (aMatName != Graphic3d_NOM_DEFAULT)
13107       {
13108         ++anArgIter;
13109         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13110         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13111         Graphic3d_MaterialAspect aMat (aMatName);
13112         aMat.SetColor (aStyle->Color());
13113         aMat.SetTransparency (aStyle->Transparency());
13114         anAspect->SetFrontMaterial (aMat);
13115         anAspect->SetInteriorColor (aStyle->Color());
13116         aStyle->SetBasicFillAreaAspect (anAspect);
13117       }
13118       else
13119       {
13120         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13121       }
13122       toRedraw = Standard_True;
13123     }
13124     else
13125     {
13126       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13127     }
13128   }
13129
13130   if (toPrint)
13131   {
13132     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13133     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13134     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13135     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13136     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13137     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13138     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13139     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13140     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13141     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13142     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13143     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13144     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13145     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13146   }
13147
13148   if (aCtx->NbSelected() != 0 && toRedraw)
13149   {
13150     aCtx->HilightSelected (Standard_True);
13151   }
13152
13153   return 0;
13154 }
13155
13156 //===============================================================================================
13157 //function : VDumpSelectionImage
13158 //purpose  :
13159 //===============================================================================================
13160 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13161                                 Standard_Integer  theArgsNb,
13162                                 const char**      theArgVec)
13163 {
13164   if (theArgsNb < 2)
13165   {
13166     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13167     return 1;
13168   }
13169
13170   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13171   if (aContext.IsNull())
13172   {
13173     std::cout << "Error: no active view.\n";
13174     return 1;
13175   }
13176
13177   TCollection_AsciiString aFile;
13178   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13179   Image_Format anImgFormat = Image_Format_BGR;
13180   Standard_Integer aPickedIndex = 1;
13181   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13182   {
13183     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13184     aParam.LowerCase();
13185     if (aParam == "-type")
13186     {
13187       if (++anArgIter >= theArgsNb)
13188       {
13189         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13190         return 1;
13191       }
13192
13193       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13194       aValue.LowerCase();
13195       if (aValue == "depth"
13196        || aValue == "normdepth"
13197        || aValue == "normalizeddepth")
13198       {
13199         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13200         anImgFormat = Image_Format_GrayF;
13201       }
13202       if (aValue == "depthinverted"
13203        || aValue == "normdepthinverted"
13204        || aValue == "normalizeddepthinverted"
13205        || aValue == "inverted")
13206       {
13207         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13208         anImgFormat = Image_Format_GrayF;
13209       }
13210       else if (aValue == "unnormdepth"
13211             || aValue == "unnormalizeddepth")
13212       {
13213         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13214         anImgFormat = Image_Format_GrayF;
13215       }
13216       else if (aValue == "objectcolor"
13217             || aValue == "object"
13218             || aValue == "color")
13219       {
13220         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13221       }
13222       else if (aValue == "entitycolor"
13223             || aValue == "entity")
13224       {
13225         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13226       }
13227       else if (aValue == "ownercolor"
13228             || aValue == "owner")
13229       {
13230         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13231       }
13232       else if (aValue == "selectionmodecolor"
13233             || aValue == "selectionmode"
13234             || aValue == "selmodecolor"
13235             || aValue == "selmode")
13236       {
13237         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13238       }
13239     }
13240     else if (aParam == "-picked"
13241           || aParam == "-pickeddepth"
13242           || aParam == "-pickedindex")
13243     {
13244       if (++anArgIter >= theArgsNb)
13245       {
13246         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13247         return 1;
13248       }
13249
13250       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13251     }
13252     else if (aFile.IsEmpty())
13253     {
13254       aFile = theArgVec[anArgIter];
13255     }
13256     else
13257     {
13258       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13259       return 1;
13260     }
13261   }
13262   if (aFile.IsEmpty())
13263   {
13264     std::cout << "Syntax error: image file name is missing.\n";
13265     return 1;
13266   }
13267
13268   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13269   Standard_Integer aWidth = 0, aHeight = 0;
13270   aView->Window()->Size (aWidth, aHeight);
13271
13272   Image_AlienPixMap aPixMap;
13273   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13274   {
13275     std::cout << "Error: can't allocate image.\n";
13276     return 1;
13277   }
13278   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13279   {
13280     std::cout << "Error: can't generate selection image.\n";
13281     return 1;
13282   }
13283   if (!aPixMap.Save (aFile))
13284   {
13285     std::cout << "Error: can't save selection image.\n";
13286     return 0;
13287   }
13288   return 0;
13289 }
13290
13291 //===============================================================================================
13292 //function : VViewCube
13293 //purpose  :
13294 //===============================================================================================
13295 static int VViewCube (Draw_Interpretor& ,
13296                       Standard_Integer  theNbArgs,
13297                       const char**      theArgVec)
13298 {
13299   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13300   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13301   if (aContext.IsNull() || aView.IsNull())
13302   {
13303     std::cout << "Error: no active view.\n";
13304     return 1;
13305   }
13306   else if (theNbArgs < 2)
13307   {
13308     std::cout << "Syntax error: wrong number arguments\n";
13309     return 1;
13310   }
13311
13312   Handle(AIS_ViewCube) aViewCube;
13313   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
13314   Quantity_Color aColorRgb;
13315   TCollection_AsciiString aName;
13316   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13317   {
13318     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13319     anArg.LowerCase();
13320     if (anUpdateTool.parseRedrawMode (anArg))
13321     {
13322       //
13323     }
13324     else if (aViewCube.IsNull())
13325     {
13326       aName = theArgVec[anArgIter];
13327       if (aName.StartsWith ("-"))
13328       {
13329         std::cout << "Syntax error: object name should be specified.\n";
13330         return 1;
13331       }
13332       Handle(AIS_InteractiveObject) aPrs;
13333       GetMapOfAIS().Find2 (aName, aPrs);
13334       aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
13335       if (aViewCube.IsNull())
13336       {
13337         aViewCube = new AIS_ViewCube();
13338         aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
13339         aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
13340         aViewCube->SetFixedAnimationLoop (false);
13341       }
13342     }
13343     else if (anArg == "-reset")
13344     {
13345       aViewCube->ResetStyles();
13346     }
13347     else if (anArg == "-color"
13348           || anArg == "-boxcolor"
13349           || anArg == "-boxsidecolor"
13350           || anArg == "-sidecolor"
13351           || anArg == "-boxedgecolor"
13352           || anArg == "-edgecolor"
13353           || anArg == "-boxcornercolor"
13354           || anArg == "-cornercolor"
13355           || anArg == "-innercolor"
13356           || anArg == "-textcolor")
13357     {
13358       Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
13359                                                            theArgVec + anArgIter + 1,
13360                                                            aColorRgb);
13361       if (aNbParsed == 0)
13362       {
13363         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
13364         return 1;
13365       }
13366       anArgIter += aNbParsed;
13367       if (anArg == "-boxcolor")
13368       {
13369         aViewCube->SetBoxColor (aColorRgb);
13370       }
13371       else if (anArg == "-boxsidecolor"
13372             || anArg == "-sidecolor")
13373       {
13374         aViewCube->BoxSideStyle()->SetColor (aColorRgb);
13375         aViewCube->SynchronizeAspects();
13376       }
13377       else if (anArg == "-boxedgecolor"
13378             || anArg == "-edgecolor")
13379       {
13380         aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
13381         aViewCube->SynchronizeAspects();
13382       }
13383       else if (anArg == "-boxcornercolor"
13384             || anArg == "-cornercolor")
13385       {
13386         aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
13387         aViewCube->SynchronizeAspects();
13388       }
13389       else if (anArg == "-innercolor")
13390       {
13391         aViewCube->SetInnerColor (aColorRgb);
13392       }
13393       else if (anArg == "-textcolor")
13394       {
13395         aViewCube->SetTextColor (aColorRgb);
13396       }
13397       else
13398       {
13399         aViewCube->SetColor (aColorRgb);
13400       }
13401     }
13402     else if (anArgIter + 1 < theNbArgs
13403           && (anArg == "-transparency"
13404            || anArg == "-boxtransparency"))
13405     {
13406       const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
13407       if (aValue < 0.0 || aValue > 1.0)
13408       {
13409         std::cout << "Syntax error: invalid transparency value " << theArgVec[anArgIter] << "\n";
13410         return 1;
13411       }
13412
13413       if (anArg == "-boxtransparency")
13414       {
13415         aViewCube->SetBoxTransparency (aValue);
13416       }
13417       else
13418       {
13419         aViewCube->SetTransparency (aValue);
13420       }
13421     }
13422     else if (anArg == "-axes"
13423           || anArg == "-edges"
13424           || anArg == "-vertices"
13425           || anArg == "-vertexes"
13426           || anArg == "-fixedanimation")
13427     {
13428       bool toShow = true;
13429       if (anArgIter + 1 < theNbArgs
13430        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toShow))
13431       {
13432         ++anArgIter;
13433       }
13434       if (anArg == "-fixedanimation")
13435       {
13436         aViewCube->SetFixedAnimationLoop (toShow);
13437       }
13438       else if (anArg == "-axes")
13439       {
13440         aViewCube->SetDrawAxes (toShow);
13441       }
13442       else if (anArg == "-edges")
13443       {
13444         aViewCube->SetDrawEdges (toShow);
13445       }
13446       else
13447       {
13448         aViewCube->SetDrawVertices (toShow);
13449       }
13450     }
13451     else if (anArg == "-yup"
13452           || anArg == "-zup")
13453     {
13454       bool isOn = true;
13455       if (anArgIter + 1 < theNbArgs
13456        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isOn))
13457       {
13458         ++anArgIter;
13459       }
13460       if (anArg == "-yup")
13461       {
13462         aViewCube->SetYup (isOn);
13463       }
13464       else
13465       {
13466         aViewCube->SetYup (!isOn);
13467       }
13468     }
13469     else if (anArgIter + 1 < theNbArgs
13470           && anArg == "-font")
13471     {
13472       aViewCube->SetFont (theArgVec[++anArgIter]);
13473     }
13474     else if (anArgIter + 1 < theNbArgs
13475           && anArg == "-fontheight")
13476     {
13477       aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
13478     }
13479     else if (anArgIter + 1 < theNbArgs
13480           && (anArg == "-size"
13481            || anArg == "-boxsize"))
13482     {
13483       aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
13484                           anArg != "-boxsize");
13485     }
13486     else if (anArgIter + 1 < theNbArgs
13487           && (anArg == "-boxfacet"
13488            || anArg == "-boxfacetextension"
13489            || anArg == "-facetextension"
13490            || anArg == "-extension"))
13491     {
13492       aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
13493     }
13494     else if (anArgIter + 1 < theNbArgs
13495           && (anArg == "-boxedgegap"
13496            || anArg == "-edgegap"))
13497     {
13498       aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
13499     }
13500     else if (anArgIter + 1 < theNbArgs
13501           && (anArg == "-boxedgeminsize"
13502            || anArg == "-edgeminsize"))
13503     {
13504       aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
13505     }
13506     else if (anArgIter + 1 < theNbArgs
13507           && (anArg == "-boxcornerminsize"
13508            || anArg == "-cornerminsize"))
13509     {
13510       aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
13511     }
13512     else if (anArgIter + 1 < theNbArgs
13513           && anArg == "-axespadding")
13514     {
13515       aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
13516     }
13517     else if (anArgIter + 1 < theNbArgs
13518           && anArg == "-roundradius")
13519     {
13520       aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
13521     }
13522     else if (anArgIter + 1 < theNbArgs
13523           && anArg == "-duration")
13524     {
13525       aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
13526     }
13527     else
13528     {
13529       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
13530       return 1;
13531     }
13532   }
13533   if (aViewCube.IsNull())
13534   {
13535     std::cout << "Syntax error: wrong number of arguments\n";
13536     return 1;
13537   }
13538
13539   ViewerTest::Display (aName, aViewCube, false);
13540   return 0;
13541 }
13542
13543 //=======================================================================
13544 //function : ViewerCommands
13545 //purpose  :
13546 //=======================================================================
13547
13548 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13549 {
13550
13551   const char *group = "ZeViewer";
13552   theCommands.Add("vinit",
13553           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13554     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13555   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13556     "\n\t\t:     [-display displayName]"
13557   #endif
13558     "\n\t\t: Creates new View window with specified name viewName."
13559     "\n\t\t: By default the new view is created in the viewer and in"
13560     "\n\t\t: graphic driver shared with active view."
13561     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13562     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13563     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13564 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13565     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13566     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13567 #endif
13568     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13569     "\n\t\t:  -width, -height width and heigth of window respectively."
13570     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13571     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13572     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13573     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13574     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13575     __FILE__,VInit,group);
13576   theCommands.Add("vclose" ,
13577     "[view_id [keep_context=0|1]]\n"
13578     "or vclose ALL - to remove all created views\n"
13579     " - removes view(viewer window) defined by its view_id.\n"
13580     " - keep_context: by default 0; if 1 and the last view is deleted"
13581     " the current context is not removed.",
13582     __FILE__,VClose,group);
13583   theCommands.Add("vactivate" ,
13584     "vactivate view_id [-noUpdate]"
13585     " - activates view(viewer window) defined by its view_id",
13586     __FILE__,VActivate,group);
13587   theCommands.Add("vviewlist",
13588     "vviewlist [format={tree, long}]"
13589     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13590     " - format: format of result output, if tree the output is a tree view;"
13591     "otherwise it's a list of full view names. By default format = tree",
13592     __FILE__,VViewList,group);
13593   theCommands.Add("vhelp" ,
13594     "vhelp            : display help on the viewer commands",
13595     __FILE__,VHelp,group);
13596   theCommands.Add("vviewproj",
13597           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13598     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13599     "\n\t\t: Setup view direction"
13600     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13601     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13602     "\n\t\t:             for example '+Z' will show front of the model,"
13603     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13604     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13605     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13606     __FILE__,VViewProj,group);
13607   theCommands.Add("vtop" ,
13608     "vtop or <T>      : Top view. Orientation +X+Y" ,
13609     __FILE__,VViewProj,group);
13610   theCommands.Add("vbottom" ,
13611     "vbottom          : Bottom view. Orientation +X-Y" ,
13612     __FILE__,VViewProj,group);
13613   theCommands.Add("vleft" ,
13614     "vleft            : Left view. Orientation -Y+Z" ,
13615     __FILE__,VViewProj,group);
13616   theCommands.Add("vright" ,
13617     "vright           : Right view. Orientation +Y+Z" ,
13618     __FILE__,VViewProj,group);
13619   theCommands.Add("vaxo" ,
13620     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13621     __FILE__,VViewProj,group);
13622   theCommands.Add("vfront" ,
13623     "vfront           : Front view. Orientation +X+Z" ,
13624     __FILE__,VViewProj,group);
13625   theCommands.Add("vback" ,
13626     "vback            : Back view. Orientation -X+Z" ,
13627     __FILE__,VViewProj,group);
13628   theCommands.Add("vpick" ,
13629     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13630     VPick,group);
13631   theCommands.Add("vfit",
13632     "vfit or <F> [-selected] [-noupdate]"
13633     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13634     __FILE__,VFit,group);
13635   theCommands.Add ("vfitarea",
13636     "vfitarea x1 y1 x2 y2"
13637     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13638     "\n\t\t: Fit view to show area located between two points"
13639     "\n\t\t: given in world 2D or 3D corrdinates.",
13640     __FILE__, VFitArea, group);
13641   theCommands.Add ("vzfit", "vzfit [scale]\n"
13642     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13643     "   \"scale\" - specifies factor to scale computed z range.\n",
13644     __FILE__, VZFit, group);
13645   theCommands.Add("vrepaint",
13646             "vrepaint [-immediate] [-continuous FPS]"
13647     "\n\t\t: force redraw of active View"
13648     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13649     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13650     "\n\t\t:                0 means no continuous rendering,"
13651     "\n\t\t:               -1 means non-stop redraws,"
13652     "\n\t\t:               >0 specifies target framerate,",
13653     __FILE__,VRepaint,group);
13654   theCommands.Add("vclear",
13655     "vclear          : vclear"
13656     "\n\t\t: remove all the object from the viewer",
13657     __FILE__,VClear,group);
13658   theCommands.Add (
13659     "vbackground",
13660     "Changes background or some background settings.\n"
13661     "\n"
13662     "Usage:\n"
13663     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13664     "  vbackground -imageMode FillType\n"
13665     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13666     "  vbackground -gradientMode FillMethod\n"
13667     "  vbackground -cubemap CubemapFile1 [CubeMapFiles2-5] [-order TilesIndexes1-6] [-invertedz]\n"
13668     "  vbackground -color Color\n"
13669     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13670     "  vbackground -default -color Color\n"
13671     "  vbackground -help\n"
13672     "\n"
13673     "Options:\n"
13674     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13675     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13676     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13677     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13678     "  -cubemap      (-cmap, -cm):                         sets environmet cubemap as background\n"
13679     "  -invertedz    (-invz, -iz):                         sets inversion of Z axis for background cubemap rendering\n"
13680     "  -order        (-o):                                 defines order of tiles in one image cubemap\n"
13681     "                                                      (has no effect in case of multi image cubemaps)\n"
13682     "  -color        (-col):                               sets background color\n"
13683     "  -default      (-def):                               sets background default gradient or color\n"
13684     "  -help         (-h):                                 outputs short help message\n"
13685     "\n"
13686     "Arguments:\n"
13687     "  Color:        Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13688     "                                  or reals within the range [0.0, 1.0]\n"
13689     "                ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13690     "                #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13691     "  FillMethod:   one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13692     "CORNER4\n"
13693     "  FillType:     one of CENTERED, TILED, STRETCH, NONE\n"
13694     "  ImageFile:    a name of the file with the image used as a background\n"
13695     "  CubemapFilei: a name of the file with one image packed cubemap or names of separate files with every cubemap side\n"
13696     "  TileIndexi:   a cubemap side index in range [0, 5] for i tile of one image packed cubemap\n",
13697     __FILE__,
13698     vbackground,
13699     group);
13700   theCommands.Add ("vsetbg",
13701                    "Loads image as background."
13702                    "\n\t\t: vsetbg ImageFile [FillType]"
13703                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13704                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13705                    __FILE__,
13706                    vbackground,
13707                    group);
13708   theCommands.Add ("vsetbgmode",
13709                    "Changes background image fill type."
13710                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13711                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13712                    __FILE__,
13713                    vbackground,
13714                    group);
13715   theCommands.Add ("vsetgradientbg",
13716                    "Mounts gradient background."
13717                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13718                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13719                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13720                    __FILE__,
13721                    vbackground,
13722                    group);
13723   theCommands.Add ("vsetgrbgmode",
13724                    "Changes gradient background fill method."
13725                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13726                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13727                    __FILE__,
13728                    vbackground,
13729                    group);
13730   theCommands.Add ("vsetcolorbg",
13731                    "Sets background color."
13732                    "\n\t\t: vsetcolorbg [-color] Color."
13733                    "\n\t\t: Alias for 'vbackground -color Color'.",
13734                    __FILE__,
13735                    vbackground,
13736                    group);
13737   theCommands.Add ("vsetdefaultbg",
13738                    "Sets default viewer background fill color (flat/gradient)."
13739                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13740                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13741                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13742                    "\n\t\t: vsetdefaultbg [-color] Color"
13743                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13744                    __FILE__,
13745                    vbackground,
13746                    group);
13747   theCommands.Add("vscale",
13748     "vscale          : vscale X Y Z",
13749     __FILE__,VScale,group);
13750   theCommands.Add("vzbufftrihedron",
13751             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13752     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13753     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13754     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13755     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13756     "\n\t\t: Displays a trihedron",
13757     __FILE__,VZBuffTrihedron,group);
13758   theCommands.Add("vrotate",
13759     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13760     "\n                : Option -mouseStart starts rotation according to the mouse position"
13761     "\n                : Option -mouseMove continues rotation with angle computed"
13762     "\n                : from last and new mouse position."
13763     "\n                : vrotate AX AY AZ [X Y Z]",
13764     __FILE__,VRotate,group);
13765   theCommands.Add("vzoom",
13766     "vzoom           : vzoom coef",
13767     __FILE__,VZoom,group);
13768   theCommands.Add("vpan",
13769     "vpan            : vpan dx dy",
13770     __FILE__,VPan,group);
13771   theCommands.Add("vcolorscale",
13772     "vcolorscale name [-noupdate|-update] [-demo]"
13773     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13774     "\n\t\t:       [-font HeightFont=20]"
13775     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13776     "\n\t\t:       [-smoothTransition {on|off}=off]"
13777     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13778     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13779     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13780     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13781     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13782     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13783     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13784     "\n\t\t:       [-xy Left=0 Bottom=0]"
13785     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13786     "\n\t\t:  -colors   - set colors for all intervals"
13787     "\n\t\t:  -color    - set color for specific interval"
13788     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13789     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13790     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13791     "\n\t\t:              at center means the center value within current interval"
13792     "\n\t\t:  -labels   - set labels for all intervals"
13793     "\n\t\t:  -freeLabels - same as -labels but does not require"
13794     "\n\t\t:              matching the number of intervals"
13795     "\n\t\t:  -label    - set label for specific interval"
13796     "\n\t\t:  -title    - set title"
13797     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13798     "\n\t\t:  -smoothTransition - swap colorscale direction"
13799     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13800     __FILE__, VColorScale, group);
13801   theCommands.Add("vgraduatedtrihedron",
13802     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13803     "\t[-namefont Name] [-valuesfont Name]\n"
13804     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13805     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13806     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13807     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13808     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13809     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13810     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13811     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13812     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13813     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13814     " - Displays or erases graduated trihedron"
13815     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13816     " - namefont - font of axes names. Default: Arial\n"
13817     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13818     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13819     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13820     " - valuesfont - font of axes values. Default: Arial\n"
13821     " - xcolor, ycolor, zcolor - color of axis and values\n"
13822     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13823     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13824     __FILE__,VGraduatedTrihedron,group);
13825   theCommands.Add("vtile" ,
13826             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13827     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13828     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13829     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13830     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13831     "\n\t\t:  -upperLeft tile offset as upper left corner",
13832     __FILE__, VTile, group);
13833   theCommands.Add("vzlayer",
13834               "vzlayer [layerId]"
13835       "\n\t\t:         [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]"
13836       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13837       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13838       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]"
13839       "\n\t\t: ZLayer list management:"
13840       "\n\t\t:   -add      add new z layer to viewer and print its id"
13841       "\n\t\t:   -insertBefore add new z layer and insert it before existing one"
13842       "\n\t\t:   -insertAfter  add new z layer and insert it after  existing one"
13843       "\n\t\t:   -delete   delete z layer"
13844       "\n\t\t:   -get      print sequence of z layers"
13845       "\n\t\t:   -settings print status of z layer settings"
13846       "\n\t\t:   -disable  disables given setting"
13847       "\n\t\t:   -enable   enables  given setting",
13848     __FILE__,VZLayer,group);
13849   theCommands.Add("vlayerline",
13850     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
13851     __FILE__,VLayerLine,group);
13852   theCommands.Add("vgrid",
13853               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
13854       "\n\t\t:       [-step X Y] [-size DX DY]"
13855       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
13856     __FILE__, VGrid, group);
13857   theCommands.Add ("vpriviledgedplane",
13858     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
13859     "\n\t\t:   Ox, Oy, Oz - plane origin"
13860     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
13861     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
13862     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
13863     __FILE__, VPriviledgedPlane, group);
13864   theCommands.Add ("vconvert",
13865     "vconvert v [Mode={window|view}]"
13866     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
13867     "\n\t\t: vconvert x y z [Mode={window|grid}]"
13868     "\n\t\t:   window - convert to window coordinates, pixels"
13869     "\n\t\t:   view   - convert to view projection plane"
13870     "\n\t\t:   grid   - convert to model coordinates, given on grid"
13871     "\n\t\t:   ray    - convert projection ray to model coordiantes"
13872     "\n\t\t: - vconvert v window : convert view to window;"
13873     "\n\t\t: - vconvert v view   : convert window to view;"
13874     "\n\t\t: - vconvert x y window : convert view to window;"
13875     "\n\t\t: - vconvert x y view : convert window to view;"
13876     "\n\t\t: - vconvert x y : convert window to model;"
13877     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
13878     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
13879     "\n\t\t: - vconvert x y z window : convert model to window;"
13880     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
13881     "\n\t\t: Converts the given coordinates to window/view/model space.",
13882     __FILE__, VConvert, group);
13883   theCommands.Add ("vfps",
13884     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
13885     __FILE__, VFps, group);
13886   theCommands.Add ("vgldebug",
13887             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
13888     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
13889     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
13890     "\n\t\t: Debug context can be requested only on Windows"
13891     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
13892     "\n\t\t:  -sync     - request synchronized debug GL context"
13893     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
13894     "\n\t\t:              which are suppressed by default,"
13895     "\n\t\t:  -glslCode - log GLSL program source code,"
13896     "\n\t\t:              which are suppressed by default,"
13897     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
13898     "\n\t\t:              which are suppressed by default",
13899     __FILE__, VGlDebug, group);
13900   theCommands.Add ("vvbo",
13901     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
13902     __FILE__, VVbo, group);
13903   theCommands.Add ("vstereo",
13904             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
13905     "\n\t\t:         [-anaglyph Filter]"
13906     "\n\t\t: Control stereo output mode. Available modes for -mode:"
13907     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
13908     "\n\t\t:                     requires driver support."
13909     "\n\t\t:                     Should be called BEFORE vinit!"
13910     "\n\t\t:  anaglyph         - Anaglyph glasses"
13911     "\n\t\t:  rowInterlaced    - row-interlaced display"
13912     "\n\t\t:  columnInterlaced - column-interlaced display"
13913     "\n\t\t:  chessBoard       - chess-board output"
13914     "\n\t\t:  sideBySide       - horizontal pair"
13915     "\n\t\t:  overUnder        - vertical   pair"
13916     "\n\t\t: Available Anaglyph filters for -anaglyph:"
13917     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
13918     "\n\t\t:  greenMagentaSimple",
13919     __FILE__, VStereo, group);
13920   theCommands.Add ("vcaps",
13921             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
13922     "\n\t\t:       [-compatibleProfile {0|1}]"
13923     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
13924     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
13925     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
13926     "\n\t\t:       [-noExtensions {0|1}] [-maxVersion Major Minor]"
13927     "\n\t\t: Modify particular graphic driver options:"
13928     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
13929     "\n\t\t:             built-in GLSL programs"
13930     "\n\t\t:            (requires compatible profile)"
13931     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
13932     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
13933     "\n\t\t:             arrays to GPU memory)"
13934     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
13935     "\n\t\t:  vsync    - switch VSync on or off"
13936     "\n\t\t:  winBuffer - allow using window buffer for rendering"
13937     "\n\t\t: Context creation options:"
13938     "\n\t\t:  softMode          - software OpenGL implementation"
13939     "\n\t\t:  compatibleProfile - backward-compatible profile"
13940     "\n\t\t:  quadbuffer        - QuadBuffer"
13941     "\n\t\t:  noExtensions      - disallow usage of extensions"
13942     "\n\t\t:  maxVersion        - force upper OpenGL version to be used"
13943     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13944     "\n\t\t: rendering paths producing the same visual result when"
13945     "\n\t\t: possible."
13946     "\n\t\t: Command is intended for testing old hardware compatibility.",
13947     __FILE__, VCaps, group);
13948   theCommands.Add ("vmemgpu",
13949     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13950     " with f option returns free memory in bytes",
13951     __FILE__, VMemGpu, group);
13952   theCommands.Add ("vreadpixel",
13953     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13954     " : Read pixel value for active view",
13955     __FILE__, VReadPixel, group);
13956   theCommands.Add("diffimage",
13957             "diffimage imageFile1 imageFile2 [diffImageFile]"
13958     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13959     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13960     "\n\t\t: Compare two images by content and generate difference image."
13961     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13962     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13963     __FILE__, VDiffImage, group);
13964   theCommands.Add ("vselect",
13965     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13966     "- emulates different types of selection:\n"
13967     "- 1) single click selection\n"
13968     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13969     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13970     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13971     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13972     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13973     " (partial inclusion - overlap - is not allowed by default)\n"
13974     "- 5) any of these selections with shift button pressed",
13975     __FILE__, VSelect, group);
13976   theCommands.Add ("vmoveto",
13977     "vmoveto [x y] [-reset]"
13978     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13979     "\n\t\t:   -reset resets current highlighting",
13980     __FILE__, VMoveTo, group);
13981   theCommands.Add ("vviewparams",
13982               "vviewparams [-args] [-scale [s]]"
13983       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13984       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13985       "\n\t\t: Manage current view parameters or prints all"
13986       "\n\t\t: current values when called without argument."
13987       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13988       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13989       "\n\t\t:   -at   [x y z] prints or sets center of look"
13990       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13991       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13992       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13993       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13994       "\n\t\t:                 or changes the size of its maximum dimension"
13995       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13996     __FILE__, VViewParams, group);
13997
13998   theCommands.Add("v2dmode",
13999     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
14000     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
14001     "\n\t\t:   mode   - switches On/Off rotation mode"
14002     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
14003     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
14004     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
14005     "\n\t\t: View camera position might be changed only by commands.",
14006     __FILE__, V2DMode, group);
14007
14008   theCommands.Add("vanimation", "Alias for vanim",
14009     __FILE__, VAnimation, group);
14010
14011   theCommands.Add("vanim",
14012             "List existing animations:"
14013     "\n\t\t:  vanim"
14014     "\n\t\t: Animation playback:"
14015     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
14016     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
14017     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
14018     "\n\t\t:   -freeLook skip camera animations"
14019     "\n\t\t:   -lockLoop disable any interactions"
14020     "\n\t\t:"
14021     "\n\t\t: Animation definition:"
14022     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
14023     "\n\t\t:        [start TimeSec] [duration TimeSec]"
14024     "\n\t\t:"
14025     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
14026     "\n\t\t: specifies nested animations."
14027     "\n\t\t: There is no syntax to explicitly add new animation,"
14028     "\n\t\t: and all non-existing animations within the name will be"
14029     "\n\t\t: implicitly created on first use (including parents)."
14030     "\n\t\t:"
14031     "\n\t\t: Each animation might define the SINGLE action (see below),"
14032     "\n\t\t: like camera transition, object transformation or custom callback."
14033     "\n\t\t: Child animations can be used for defining concurrent actions."
14034     "\n\t\t:"
14035     "\n\t\t: Camera animation:"
14036     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
14037     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
14038     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
14039     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
14040     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
14041     "\n\t\t:   -atX    camera Center positions pair"
14042     "\n\t\t:   -upX    camera Up directions pair"
14043     "\n\t\t:   -scaleX camera Scale factors pair"
14044     "\n\t\t: Object animation:"
14045     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
14046     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
14047     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
14048     "\n\t\t:   -locX   object Location points pair (translation)"
14049     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
14050     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
14051     "\n\t\t: Custom callback:"
14052     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
14053     "\n\t\t:   %Pts        overall animation presentation timestamp"
14054     "\n\t\t:   %LocalPts   local animation timestamp"
14055     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
14056     "\n\t\t:"
14057     "\n\t\t: Video recording:"
14058     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
14059     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
14060     "\n\t\t:             [-crf Value] [-preset Preset]"
14061     "\n\t\t:   -fps     video framerate"
14062     "\n\t\t:   -format  file format, container (matroska, etc.)"
14063     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
14064     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
14065     "\n\t\t:   -crf     constant rate factor (specific to codec)"
14066     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
14067     __FILE__, VAnimation, group);
14068
14069   theCommands.Add("vchangeselected",
14070     "vchangeselected shape"
14071     "- adds to shape to selection or remove one from it",
14072                 __FILE__, VChangeSelected, group);
14073   theCommands.Add ("vnbselected",
14074     "vnbselected"
14075     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14076   theCommands.Add ("vcamera",
14077               "vcamera [PrsName] [-ortho] [-projtype]"
14078       "\n\t\t:         [-persp]"
14079       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14080       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14081       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14082       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14083       "\n\t\t: Manages camera parameters."
14084       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14085       "\n\t\t: Prints current value when option called without argument."
14086       "\n\t\t: Orthographic camera:"
14087       "\n\t\t:   -ortho      activate orthographic projection"
14088       "\n\t\t: Perspective camera:"
14089       "\n\t\t:   -persp      activate perspective  projection (mono)"
14090       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14091       "\n\t\t:   -distance   distance of eye from camera center"
14092       "\n\t\t: Stereoscopic camera:"
14093       "\n\t\t:   -stereo     perspective  projection (stereo)"
14094       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14095       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14096       "\n\t\t:   -iod        intraocular distance value"
14097       "\n\t\t:   -iodType    distance type, absolute or relative"
14098       "\n\t\t:   -zfocus     stereographic focus value"
14099       "\n\t\t:   -zfocusType focus type, absolute or relative",
14100     __FILE__, VCamera, group);
14101   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14102     "- vautozfit [on={1|0}] [scale]\n"
14103     "    Prints or changes parameters of automatic z-fit mode:\n"
14104     "   \"on\" - turns automatic z-fit on or off\n"
14105     "   \"scale\" - specifies factor to scale computed z range.\n",
14106     __FILE__, VAutoZFit, group);
14107   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14108     "   vzrange                - without parameters shows current values\n"
14109     "   vzrange [znear] [zfar] - applies provided values to view",
14110     __FILE__,VZRange, group);
14111   theCommands.Add ("vpurgedisplay",
14112     "vpurgedisplay"
14113     "- removes structures which don't belong to objects displayed in neutral point",
14114     __FILE__, VPurgeDisplay, group);
14115   theCommands.Add("vsetviewsize",
14116     "vsetviewsize size",
14117     __FILE__,VSetViewSize,group);
14118   theCommands.Add("vmoveview",
14119     "vmoveview Dx Dy Dz [Start = 1|0]",
14120     __FILE__,VMoveView,group);
14121   theCommands.Add("vtranslateview",
14122     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14123     __FILE__,VTranslateView,group);
14124   theCommands.Add("vturnview",
14125     "vturnview Ax Ay Az [Start = 1|0]",
14126     __FILE__,VTurnView,group);
14127   theCommands.Add("vtextureenv",
14128     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14129     "or user-defined file and optionally applying texture mapping parameters\n"
14130     "                  Usage:\n"
14131     "                  vtextureenv off - disables environment mapping\n"
14132     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14133     "                              std_texture = (0..7)\n"
14134     "                              rep         = {clamp|repeat}\n"
14135     "                              mod         = {decal|modulate}\n"
14136     "                              flt         = {nearest|bilinear|trilinear}\n"
14137     "                              ss, st      - scale factors for s and t texture coordinates\n"
14138     "                              ts, tt      - translation for s and t texture coordinates\n"
14139     "                              rot         - texture rotation angle in degrees",
14140     __FILE__, VTextureEnv, group);
14141   theCommands.Add("vhlr",
14142             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14143       "\n\t\t: Hidden Line Removal algorithm."
14144       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14145       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14146     __FILE__,VHLR,group);
14147   theCommands.Add("vhlrtype",
14148               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14149       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14150       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14151       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14152       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14153     __FILE__,VHLRType,group);
14154   theCommands.Add("vclipplane",
14155               "vclipplane planeName [{0|1}]"
14156       "\n\t\t:   [-equation1 A B C D]"
14157       "\n\t\t:   [-equation2 A B C D]"
14158       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14159       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14160       "\n\t\t:   [-maxPlanes]"
14161       "\n\t\t:   [-capping {0|1}]"
14162       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14163       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14164       "\n\t\t:       [-texRotate Angle]"
14165       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14166       "\n\t\t:       [-useObjShader {0|1}]"
14167       "\n\t\t: Clipping planes management:"
14168       "\n\t\t:   -maxPlanes   print plane limit for view"
14169       "\n\t\t:   -delete      delete plane with given name"
14170       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14171       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14172       "\n\t\t:                applied to active View when list is omitted"
14173       "\n\t\t:   -equation A B C D change plane equation"
14174       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14175       "\n\t\t: Capping options:"
14176       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14177       "\n\t\t:   -color R G B          set capping color"
14178       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14179       "\n\t\t:   -texName Texture      set capping texture"
14180       "\n\t\t:   -texScale SX SY       set capping tex scale"
14181       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14182       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14183       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14184       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14185       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14186       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14187       __FILE__, VClipPlane, group);
14188   theCommands.Add("vdefaults",
14189                "vdefaults [-absDefl value]"
14190        "\n\t\t:           [-devCoeff value]"
14191        "\n\t\t:           [-angDefl value]"
14192        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14193     , __FILE__, VDefaults, group);
14194   theCommands.Add("vlight",
14195     "tool to manage light sources, without arguments shows list of lights."
14196     "\n    Main commands: "
14197     "\n      '-clear' to clear lights"
14198     "\n      '-{def}aults' to load deafault lights"
14199     "\n      '-add' <type> to add any light source"
14200     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14201     "\n      'change' <lightId> to edit light source with specified lightId"
14202     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14203     "\n        -layer Id"
14204     "\n        -{pos}ition X Y Z"
14205     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14206     "\n        -color colorName"
14207     "\n        -{head}light 0|1"
14208     "\n        -{sm}oothness value"
14209     "\n        -{int}ensity value"
14210     "\n        -{constAtten}uation value"
14211     "\n        -{linearAtten}uation value"
14212     "\n        -angle angleDeg"
14213     "\n        -{spotexp}onent value"
14214     "\n        -local|-global"
14215     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14216     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14217     __FILE__, VLight, group);
14218   theCommands.Add("vraytrace",
14219             "vraytrace [0|1]"
14220     "\n\t\t: Turns on/off ray-tracing renderer."
14221     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14222     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14223     __FILE__, VRenderParams, group);
14224   theCommands.Add("vrenderparams",
14225     "\n    Manages rendering parameters: "
14226     "\n      '-raster'                   Disables GPU ray-tracing"
14227     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14228     "\n      '-lineFeather  > 0'         Sets line feather factor"
14229     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14230     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14231     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14232     "\n      '-rendScale    value        Rendering resolution scale factor"
14233     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14234     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14235     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14236     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14237     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14238     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14239     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14240     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14241     "\n      '-env          on|off'      Enables/disables environment map background"
14242     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14243     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14244     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14245     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14246     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14247     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14248     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14249     "\n      '-shadingModel model'       Controls shading model from enumeration"
14250     "\n                                  color, flat, gouraud, phong"
14251     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14252     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14253     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14254     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14255     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14256     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14257     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
14258     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14259     "\n                                  Show/hide performance counters (flags can be combined)"
14260     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14261     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14262     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14263     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14264     "\n                                        set state to check structures culled previously."
14265     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14266     "\n    Command is intended to control presentation quality depending on"
14267     "\n    hardware capabilities and performance.",
14268     __FILE__, VRenderParams, group);
14269   theCommands.Add("vstatprofiler",
14270     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14271     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14272     "\n                |triagles|points|geomMem|textureMem|frameMem"
14273     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14274     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14275     "\n                [-noredraw]"
14276     "\n\t\t: Prints rendering statistics."
14277     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14278     "\n\t\t:   else - print all performance counters set previously."
14279     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14280     __FILE__, VStatProfiler, group);
14281   theCommands.Add ("vplace",
14282             "vplace dx dy"
14283     "\n\t\t: Places the point (in pixels) at the center of the window",
14284     __FILE__, VPlace, group);
14285   theCommands.Add("vxrotate",
14286     "vxrotate",
14287     __FILE__,VXRotate,group);
14288
14289     theCommands.Add("vmanipulator",
14290       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14291       "\n    tool to create and manage AIS manipulators."
14292       "\n    Options: "
14293       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14294       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14295       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14296       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14297       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
14298       "\n                                          by default it is displayed in all views of the current viewer"
14299       "\n      '-detach'                           detach manipulator"
14300       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14301       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14302       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14303       "\n      '-move x y z'                     - move attached object"
14304       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14305       "\n      '-scale factor'                   - scale attached object"
14306       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14307       "\n      '-followTranslation {0|1}'        - set following translation transform"
14308       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14309       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14310       "\n      '-gap value'                      - set gap between sub-parts"
14311       "\n      '-part axis mode    {0|1}'        - set visual part"
14312       "\n      '-parts axis mode   {0|1}'        - set visual part"
14313       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14314       "\n      '-size value'                     - set size of manipulator"
14315       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14316     __FILE__, VManipulator, group);
14317
14318   theCommands.Add("vselprops",
14319     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14320     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14321     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14322     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14323     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14324     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14325     "\n                            'first'   to pick first acceptable (default)"
14326     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14327     "\n    -pixTol    value        : sets up pixel tolerance"
14328     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14329     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14330     "\n    -color     {name|r g b} : sets highlight color"
14331     "\n    -transp    value        : sets transparency coefficient for highlight"
14332     "\n    -material  material     : sets highlight material"
14333     "\n    -print                  : prints current state of all mentioned parameters",
14334     __FILE__, VSelectionProperties, group);
14335   theCommands.Add ("vhighlightselected",
14336                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14337                    __FILE__, VSelectionProperties, group);
14338
14339   theCommands.Add ("vseldump",
14340                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14341                    "\n\t\t: Generate an image based on detection results:"
14342                    "\n\t\t:   depth       normalized depth values"
14343                    "\n\t\t:   unnormDepth unnormalized depth values"
14344                    "\n\t\t:   object      color of detected object"
14345                    "\n\t\t:   owner       color of detected owner"
14346                    "\n\t\t:   selMode     color of selection mode"
14347                    "\n\t\t:   entity      color of etected entity",
14348                    __FILE__, VDumpSelectionImage, group);
14349
14350   theCommands.Add ("vviewcube",
14351                    "vviewcube name"
14352                    "\n\t\t: Displays interactive view manipualtion object."
14353                    "\n\t\t: Options: "
14354                    "\n\t\t:   -reset                   reset geomertical and visual attributes'"
14355                    "\n\t\t:   -size Size               adapted size of View Cube"
14356                    "\n\t\t:   -boxSize Size            box size"
14357                    "\n\t\t:   -axes {0|1 }             show/hide axes (trihedron)"
14358                    "\n\t\t:   -edges {0|1}             show/hide edges of View Cube"
14359                    "\n\t\t:   -vertices {0|1}          show/hide vertices of View Cube"
14360                    "\n\t\t:   -Yup {0|1} -Zup {0|1}    set Y-up or Z-up view orientation"
14361                    "\n\t\t:   -color Color             color of View Cube"
14362                    "\n\t\t:   -boxColor Color          box color"
14363                    "\n\t\t:   -boxSideColor Color      box sides color"
14364                    "\n\t\t:   -boxEdgeColor Color      box edges color"
14365                    "\n\t\t:   -boxCornerColor Color    box corner color"
14366                    "\n\t\t:   -textColor Color         color of side text of view cube"
14367                    "\n\t\t:   -innerColor Color        inner box color"
14368                    "\n\t\t:   -transparency Value      transparency of object within [0, 1] range"
14369                    "\n\t\t:   -boxTransparency Value   transparency of box    within [0, 1] range"
14370                    "\n\t\t:   -font Name               font name"
14371                    "\n\t\t:   -fontHeight Value        font height"
14372                    "\n\t\t:   -boxFacetExtension Value box facet extension"
14373                    "\n\t\t:   -boxEdgeGap Value        gap between box edges and box sides"
14374                    "\n\t\t:   -boxEdgeMinSize Value    minimal box edge size"
14375                    "\n\t\t:   -boxCornerMinSize Value  minimal box corner size"
14376                    "\n\t\t:   -axesPadding Value       padding between box and arrows"
14377                    "\n\t\t:   -roundRadius Value       relative radius of corners of sides within [0.0, 0.5] range"
14378                    "\n\t\t:   -fixedanimation {0|1}    uninterruptible animation loop"
14379                    "\n\t\t:   -duration Seconds        animation duration in seconds",
14380     __FILE__, VViewCube, group);
14381
14382 }