90c890d9050216bb0ad7e45a07cdfc22f91c2b39
[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.SetAmbientColor  (Quantity_NOC_BLACK);
7207       aMat.SetDiffuseColor  (Quantity_NOC_WHITE);
7208       aMat.SetSpecularColor (Quantity_NOC_BLACK);
7209       aMat.SetEmissiveColor (Quantity_NOC_BLACK);
7210       aFillAspect->SetFrontMaterial (aMat);
7211       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7212       aFillAspect->SetTextureMapOn();
7213     }
7214     {
7215       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7216       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7217       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7218       myDrawer->SetTextAspect (aTextAspect);
7219     }
7220     {
7221       const gp_Dir aNorm (0.0, 0.0, 1.0);
7222       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7223       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7224       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7225       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7226       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7227       myTris->AddEdge (1);
7228       myTris->AddEdge (2);
7229       myTris->AddEdge (3);
7230       myTris->AddEdge (3);
7231       myTris->AddEdge (2);
7232       myTris->AddEdge (4);
7233
7234       myRect = new Graphic3d_ArrayOfPolylines (4);
7235       myRect->AddVertex (myTris->Vertice (1));
7236       myRect->AddVertex (myTris->Vertice (3));
7237       myRect->AddVertex (myTris->Vertice (4));
7238       myRect->AddVertex (myTris->Vertice (2));
7239     }
7240   }
7241
7242   //! Returns TRUE for accepted display modes.
7243   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7244
7245   //! Compute presentation.
7246   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7247   {
7248     switch (theMode)
7249     {
7250       case 0:
7251       {
7252         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7253         aGroup->AddPrimitiveArray (myTris);
7254         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7255         aGroup->AddPrimitiveArray (myRect);
7256         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7257         return;
7258       }
7259       case 1:
7260       {
7261         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7262         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7263         aGroup->AddPrimitiveArray (myRect);
7264         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7265         return;
7266       }
7267     }
7268   }
7269
7270   //! Compute selection.
7271   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7272   {
7273     if (theMode == 0)
7274     {
7275       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7276       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7277       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7278       theSel->Add (aSensitive);
7279     }
7280   }
7281
7282 private:
7283   Handle(Graphic3d_ArrayOfTriangles) myTris;
7284   Handle(Graphic3d_ArrayOfPolylines) myRect;
7285   TCollection_AsciiString myLabel;
7286   Standard_Real myWidth;
7287   Standard_Real myHeight;
7288 };
7289
7290 //==============================================================================
7291 //function : VDiffImage
7292 //purpose  : The draw-command compares two images.
7293 //==============================================================================
7294
7295 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7296 {
7297   if (theArgNb < 3)
7298   {
7299     std::cout << "Syntax error: not enough arguments.\n";
7300     return 1;
7301   }
7302
7303   Standard_Integer anArgIter = 1;
7304   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7305   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7306   TCollection_AsciiString aDiffImagePath;
7307   Standard_Real    aTolColor        = -1.0;
7308   Standard_Integer toBlackWhite     = -1;
7309   Standard_Integer isBorderFilterOn = -1;
7310   Standard_Boolean isOldSyntax = Standard_False;
7311   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7312   for (; anArgIter < theArgNb; ++anArgIter)
7313   {
7314     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7315     anArg.LowerCase();
7316     if (anArgIter + 1 < theArgNb
7317      && (anArg == "-toleranceofcolor"
7318       || anArg == "-tolerancecolor"
7319       || anArg == "-tolerance"
7320       || anArg == "-toler"))
7321     {
7322       aTolColor = Atof (theArgVec[++anArgIter]);
7323       if (aTolColor < 0.0 || aTolColor > 1.0)
7324       {
7325         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7326         return 1;
7327       }
7328     }
7329     else if (anArg == "-blackwhite")
7330     {
7331       Standard_Boolean toEnable = Standard_True;
7332       if (anArgIter + 1 < theArgNb
7333        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7334       {
7335         ++anArgIter;
7336       }
7337       toBlackWhite = toEnable ? 1 : 0;
7338     }
7339     else if (anArg == "-borderfilter")
7340     {
7341       Standard_Boolean toEnable = Standard_True;
7342       if (anArgIter + 1 < theArgNb
7343        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7344       {
7345         ++anArgIter;
7346       }
7347       isBorderFilterOn = toEnable ? 1 : 0;
7348     }
7349     else if (anArg == "-exitonclose")
7350     {
7351       ViewerTest_EventManager::ToExitOnCloseView() = true;
7352       if (anArgIter + 1 < theArgNb
7353        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7354       {
7355         ++anArgIter;
7356       }
7357     }
7358     else if (anArg == "-closeonescape"
7359           || anArg == "-closeonesc")
7360     {
7361       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7362       if (anArgIter + 1 < theArgNb
7363        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7364       {
7365         ++anArgIter;
7366       }
7367     }
7368     else if (anArgIter + 3 < theArgNb
7369           && anArg == "-display")
7370     {
7371       aViewName   = theArgVec[++anArgIter];
7372       aPrsNameRef = theArgVec[++anArgIter];
7373       aPrsNameNew = theArgVec[++anArgIter];
7374       if (anArgIter + 1 < theArgNb
7375       && *theArgVec[anArgIter + 1] != '-')
7376       {
7377         aPrsNameDiff = theArgVec[++anArgIter];
7378       }
7379     }
7380     else if (aTolColor < 0.0
7381           && anArg.IsRealValue())
7382     {
7383       isOldSyntax = Standard_True;
7384       aTolColor = anArg.RealValue();
7385       if (aTolColor < 0.0 || aTolColor > 1.0)
7386       {
7387         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7388         return 1;
7389       }
7390     }
7391     else if (isOldSyntax
7392           && toBlackWhite == -1
7393           && (anArg == "0" || anArg == "1"))
7394     {
7395       toBlackWhite = anArg == "1" ? 1 : 0;
7396     }
7397     else if (isOldSyntax
7398           && isBorderFilterOn == -1
7399           && (anArg == "0" || anArg == "1"))
7400     {
7401       isBorderFilterOn = anArg == "1" ? 1 : 0;
7402     }
7403     else if (aDiffImagePath.IsEmpty())
7404     {
7405       aDiffImagePath = theArgVec[anArgIter];
7406     }
7407     else
7408     {
7409       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7410       return 1;
7411     }
7412   }
7413
7414   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7415   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7416   if (!anImgRef->Load (anImgPathRef))
7417   {
7418     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7419     return 1;
7420   }
7421   if (!anImgNew->Load (anImgPathNew))
7422   {
7423     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7424     return 1;
7425   }
7426
7427   // compare the images
7428   Image_Diff aComparer;
7429   Standard_Integer aDiffColorsNb = -1;
7430   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7431   {
7432     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7433     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7434     aDiffColorsNb = aComparer.Compare();
7435     theDI << aDiffColorsNb << "\n";
7436   }
7437
7438   // save image of difference
7439   Handle(Image_AlienPixMap) aDiff;
7440   if (aDiffColorsNb > 0
7441   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7442   {
7443     aDiff = new Image_AlienPixMap();
7444     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7445     {
7446       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7447       return 1;
7448     }
7449     aComparer.SaveDiffImage (*aDiff);
7450     if (!aDiffImagePath.IsEmpty()
7451      && !aDiff->Save (aDiffImagePath))
7452     {
7453       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7454       return 1;
7455     }
7456   }
7457
7458   if (aViewName.IsEmpty())
7459   {
7460     return 0;
7461   }
7462
7463   ViewerTest_Names aViewNames (aViewName);
7464   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7465   {
7466     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7467     theDI.Eval (aCommand.ToCString());
7468   }
7469
7470   Standard_Integer aPxLeft = 0;
7471   Standard_Integer aPxTop  = 0;
7472   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7473   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7474                               ? int(anImgRef->SizeY() * 2)
7475                               : int(anImgRef->SizeY());
7476   TCollection_AsciiString aDisplayName;
7477   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7478                                                             aViewName, aDisplayName);
7479
7480   Standard_Real aRatio = anImgRef->Ratio();
7481   Standard_Real aSizeX = 1.0;
7482   Standard_Real aSizeY = aSizeX / aRatio;
7483   {
7484     OSD_Path aPath (anImgPathRef);
7485     TCollection_AsciiString aLabelRef;
7486     if (!aPath.Name().IsEmpty())
7487     {
7488       aLabelRef = aPath.Name() + aPath.Extension();
7489     }
7490     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7491
7492     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7493     gp_Trsf aTrsfRef;
7494     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7495     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7496     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7497   }
7498   {
7499     OSD_Path aPath (anImgPathNew);
7500     TCollection_AsciiString aLabelNew;
7501     if (!aPath.Name().IsEmpty())
7502     {
7503       aLabelNew = aPath.Name() + aPath.Extension();
7504     }
7505     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7506
7507     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7508     gp_Trsf aTrsfRef;
7509     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7510     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7511     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7512   }
7513   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7514   if (!aDiff.IsNull())
7515   {
7516     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7517     gp_Trsf aTrsfDiff;
7518     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7519     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7520   }
7521   if (!aPrsNameDiff.IsEmpty())
7522   {
7523     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7524   }
7525   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7526   ViewerTest::CurrentView()->FitAll();
7527   return 0;
7528 }
7529
7530 //=======================================================================
7531 //function : VSelect
7532 //purpose  : Emulates different types of selection by mouse:
7533 //           1) single click selection
7534 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7535 //           3) selection with polygon having corners at
7536 //           pixel positions (x1,y1),...,(xn,yn)
7537 //           4) any of these selections with shift button pressed
7538 //=======================================================================
7539 static Standard_Integer VSelect (Draw_Interpretor& ,
7540                                  Standard_Integer theNbArgs,
7541                                  const char** theArgVec)
7542 {
7543   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7544   if (aCtx.IsNull())
7545   {
7546     std::cout << "Error: no active View\n";
7547     return 1;
7548   }
7549
7550   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7551   bool isShiftSelection = false, toAllowOverlap = false;
7552   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7553   {
7554     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7555     anArg.LowerCase();
7556     if (anArg == "-allowoverlap")
7557     {
7558       toAllowOverlap = true;
7559       if (anArgIter + 1 < theNbArgs
7560        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7561       {
7562         ++anArgIter;
7563       }
7564     }
7565     else if (anArgIter + 1 < theNbArgs
7566           && anArg.IsIntegerValue()
7567           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7568     {
7569       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7570       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7571     }
7572     else if (anArgIter + 1 == theNbArgs
7573           && anArg.IsIntegerValue())
7574     {
7575       isShiftSelection = anArg.IntegerValue() == 1;
7576     }
7577     else
7578     {
7579       std::cout << "Syntax error at '" << anArg << "'\n";
7580       return 1;
7581     }
7582   }
7583   if (toAllowOverlap
7584    && aPnts.Length() != 2)
7585   {
7586     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7587     return 1;
7588   }
7589   if (toAllowOverlap)
7590   {
7591     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7592   }
7593
7594   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7595   if (aPnts.IsEmpty())
7596   {
7597     if (isShiftSelection)
7598     {
7599       aCtx->ShiftSelect (false);
7600     }
7601     else
7602     {
7603       aCtx->Select (false);
7604     }
7605     aCtx->CurrentViewer()->Invalidate();
7606   }
7607   else if (aPnts.Length() == 2)
7608   {
7609     if (toAllowOverlap
7610      && aPnts.First().y() < aPnts.Last().y())
7611     {
7612       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7613     }
7614     else if (!toAllowOverlap
7615            && aPnts.First().y() > aPnts.Last().y())
7616     {
7617       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7618     }
7619     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7620   }
7621   else
7622   {
7623     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7624   }
7625   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7626   return 0;
7627 }
7628
7629 //=======================================================================
7630 //function : VMoveTo
7631 //purpose  : Emulates cursor movement to defined pixel position
7632 //=======================================================================
7633 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7634                                 Standard_Integer theNbArgs,
7635                                 const char**     theArgVec)
7636 {
7637   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7638   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7639   if (aContext.IsNull())
7640   {
7641     std::cout << "Error: no active View\n";
7642     return 1;
7643   }
7644
7645   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7646   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7647   {
7648     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7649     anArgStr.LowerCase();
7650     if (anArgStr == "-reset"
7651      || anArgStr == "-clear")
7652     {
7653       if (anArgIter + 1 < theNbArgs)
7654       {
7655         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7656         return 1;
7657       }
7658
7659       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7660                                        && aContext->CurrentViewer()->GridEcho();
7661       if (toEchoGrid)
7662       {
7663         aContext->CurrentViewer()->HideGridEcho (aView);
7664       }
7665       if (aContext->ClearDetected() || toEchoGrid)
7666       {
7667         aContext->CurrentViewer()->RedrawImmediate();
7668       }
7669       return 0;
7670     }
7671     else if (aMousePos.x() == IntegerLast()
7672           && anArgStr.IsIntegerValue())
7673     {
7674       aMousePos.x() = anArgStr.IntegerValue();
7675     }
7676     else if (aMousePos.y() == IntegerLast()
7677           && anArgStr.IsIntegerValue())
7678     {
7679       aMousePos.y() = anArgStr.IntegerValue();
7680     }
7681     else
7682     {
7683       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7684       return 1;
7685     }
7686   }
7687
7688   if (aMousePos.x() == IntegerLast()
7689    || aMousePos.y() == IntegerLast())
7690   {
7691     std::cout << "Syntax error: wrong number of arguments\n";
7692     return 1;
7693   }
7694
7695   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7696   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7697   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7698
7699   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7700   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7701   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7702   {
7703     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7704     {
7705       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7706       break;
7707     }
7708   }
7709   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7710   return 0;
7711 }
7712
7713 namespace
7714 {
7715   //! Global map storing all animations registered in ViewerTest.
7716   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7717
7718   //! The animation calling the Draw Harness command.
7719   class ViewerTest_AnimationProc : public AIS_Animation
7720   {
7721   public:
7722
7723     //! Main constructor.
7724     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7725                               Draw_Interpretor* theDI,
7726                               const TCollection_AsciiString& theCommand)
7727     : AIS_Animation (theAnimationName),
7728       myDrawInter(theDI),
7729       myCommand  (theCommand)
7730     {
7731       //
7732     }
7733
7734   protected:
7735
7736     //! Evaluate the command.
7737     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7738     {
7739       TCollection_AsciiString aCmd = myCommand;
7740       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7741       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7742       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7743       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7744       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7745       myDrawInter->Eval (aCmd.ToCString());
7746     }
7747
7748     //! Find the keyword in the command and replace it with value.
7749     //! @return the position of the keyword to pass value
7750     void replace (TCollection_AsciiString&       theCmd,
7751                   const TCollection_AsciiString& theKey,
7752                   const TCollection_AsciiString& theVal)
7753     {
7754       TCollection_AsciiString aCmd (theCmd);
7755       aCmd.LowerCase();
7756       const Standard_Integer aPos = aCmd.Search (theKey);
7757       if (aPos == -1)
7758       {
7759         return;
7760       }
7761
7762       TCollection_AsciiString aPart1, aPart2;
7763       Standard_Integer aPart1To = aPos - 1;
7764       if (aPart1To >= 1
7765        && aPart1To <= theCmd.Length())
7766       {
7767         aPart1 = theCmd.SubString (1, aPart1To);
7768       }
7769
7770       Standard_Integer aPart2From = aPos + theKey.Length();
7771       if (aPart2From >= 1
7772        && aPart2From <= theCmd.Length())
7773       {
7774         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7775       }
7776
7777       theCmd = aPart1 + theVal + aPart2;
7778     }
7779
7780   protected:
7781
7782     Draw_Interpretor*       myDrawInter;
7783     TCollection_AsciiString myCommand;
7784
7785   };
7786
7787   //! Replace the animation with the new one.
7788   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7789                                 Handle(AIS_Animation)&       theAnimation,
7790                                 const Handle(AIS_Animation)& theAnimationNew)
7791   {
7792     theAnimationNew->CopyFrom (theAnimation);
7793     if (!theParentAnimation.IsNull())
7794     {
7795       theParentAnimation->Replace (theAnimation, theAnimationNew);
7796     }
7797     else
7798     {
7799       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7800       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7801     }
7802     theAnimation = theAnimationNew;
7803   }
7804
7805   //! Parse the point.
7806   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7807   {
7808     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7809     if (!anXYZ[0].IsRealValue()
7810      || !anXYZ[1].IsRealValue()
7811      || !anXYZ[2].IsRealValue())
7812     {
7813       return Standard_False;
7814     }
7815
7816     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7817     return Standard_True;
7818   }
7819
7820   //! Parse the quaternion.
7821   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7822   {
7823     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7824     if (!anXYZW[0].IsRealValue()
7825      || !anXYZW[1].IsRealValue()
7826      || !anXYZW[2].IsRealValue()
7827      || !anXYZW[3].IsRealValue())
7828     {
7829       return Standard_False;
7830     }
7831
7832     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7833     return Standard_True;
7834   }
7835
7836   //! Auxiliary class for flipping image upside-down.
7837   class ImageFlipper
7838   {
7839   public:
7840
7841     //! Empty constructor.
7842     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7843
7844     //! Perform flipping.
7845     Standard_Boolean FlipY (Image_PixMap& theImage)
7846     {
7847       if (theImage.IsEmpty()
7848        || theImage.SizeX() == 0
7849        || theImage.SizeY() == 0)
7850       {
7851         return Standard_False;
7852       }
7853
7854       const Standard_Size aRowSize = theImage.SizeRowBytes();
7855       if (myTmp.Size() < aRowSize
7856       && !myTmp.Allocate (aRowSize))
7857       {
7858         return Standard_False;
7859       }
7860
7861       // for odd height middle row should be left as is
7862       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7863       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7864       {
7865         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7866         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7867         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7868         memcpy (aTop,               aBot,         aRowSize);
7869         memcpy (aBot,               myTmp.Data(), aRowSize);
7870       }
7871       return Standard_True;
7872     }
7873
7874   private:
7875     NCollection_Buffer myTmp;
7876   };
7877
7878 }
7879
7880 //=================================================================================================
7881 //function : VViewParams
7882 //purpose  : Gets or sets AIS View characteristics
7883 //=================================================================================================
7884 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7885 {
7886   Handle(V3d_View) aView = ViewerTest::CurrentView();
7887   if (aView.IsNull())
7888   {
7889     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7890     return 1;
7891   }
7892
7893   Standard_Boolean toSetProj     = Standard_False;
7894   Standard_Boolean toSetUp       = Standard_False;
7895   Standard_Boolean toSetAt       = Standard_False;
7896   Standard_Boolean toSetEye      = Standard_False;
7897   Standard_Boolean toSetScale    = Standard_False;
7898   Standard_Boolean toSetSize     = Standard_False;
7899   Standard_Boolean toSetCenter2d = Standard_False;
7900   Standard_Real    aViewScale = aView->Scale();
7901   Standard_Real    aViewSize  = 1.0;
7902   Graphic3d_Vec2i  aCenter2d;
7903   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7904   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7905   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7906   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7907   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7908   if (theArgsNb == 1)
7909   {
7910     // print all of the available view parameters
7911     char aText[4096];
7912     Sprintf (aText,
7913              "Scale: %g\n"
7914              "Proj:  %12g %12g %12g\n"
7915              "Up:    %12g %12g %12g\n"
7916              "At:    %12g %12g %12g\n"
7917              "Eye:   %12g %12g %12g\n",
7918               aViewScale,
7919               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7920               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7921               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7922               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7923     theDi << aText;
7924     return 0;
7925   }
7926
7927   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7928   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7929   {
7930     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7931     anArg.LowerCase();
7932     if (anUpdateTool.parseRedrawMode (anArg))
7933     {
7934       continue;
7935     }
7936     else if (anArg == "-cmd"
7937           || anArg == "-command"
7938           || anArg == "-args")
7939     {
7940       char aText[4096];
7941       Sprintf (aText,
7942                "-scale %g "
7943                "-proj %g %g %g "
7944                "-up %g %g %g "
7945                "-at %g %g %g\n",
7946                 aViewScale,
7947                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7948                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7949                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7950       theDi << aText;
7951     }
7952     else if (anArg == "-scale"
7953           || anArg == "-size")
7954     {
7955       if (anArgIter + 1 < theArgsNb
7956        && *theArgVec[anArgIter + 1] != '-')
7957       {
7958         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7959         if (aValueArg.IsRealValue())
7960         {
7961           ++anArgIter;
7962           if (anArg == "-scale")
7963           {
7964             toSetScale = Standard_True;
7965             aViewScale = aValueArg.RealValue();
7966           }
7967           else if (anArg == "-size")
7968           {
7969             toSetSize = Standard_True;
7970             aViewSize = aValueArg.RealValue();
7971           }
7972           continue;
7973         }
7974       }
7975       if (anArg == "-scale")
7976       {
7977         theDi << "Scale: " << aView->Scale() << "\n";
7978       }
7979       else if (anArg == "-size")
7980       {
7981         Graphic3d_Vec2d aSizeXY;
7982         aView->Size (aSizeXY.x(), aSizeXY.y());
7983         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7984       }
7985     }
7986     else if (anArg == "-eye"
7987           || anArg == "-at"
7988           || anArg == "-up"
7989           || anArg == "-proj")
7990     {
7991       if (anArgIter + 3 < theArgsNb)
7992       {
7993         gp_XYZ anXYZ;
7994         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7995         {
7996           anArgIter += 3;
7997           if (anArg == "-eye")
7998           {
7999             toSetEye = Standard_True;
8000             aViewEye = anXYZ;
8001           }
8002           else if (anArg == "-at")
8003           {
8004             toSetAt = Standard_True;
8005             aViewAt = anXYZ;
8006           }
8007           else if (anArg == "-up")
8008           {
8009             toSetUp = Standard_True;
8010             aViewUp = anXYZ;
8011           }
8012           else if (anArg == "-proj")
8013           {
8014             toSetProj = Standard_True;
8015             aViewProj = anXYZ;
8016           }
8017           continue;
8018         }
8019       }
8020
8021       if (anArg == "-eye")
8022       {
8023         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
8024       }
8025       else if (anArg == "-at")
8026       {
8027         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
8028       }
8029       else if (anArg == "-up")
8030       {
8031         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
8032       }
8033       else if (anArg == "-proj")
8034       {
8035         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
8036       }
8037     }
8038     else if (anArg == "-center")
8039     {
8040       if (anArgIter + 2 < theArgsNb)
8041       {
8042         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
8043         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
8044         if (anX.IsIntegerValue()
8045          && anY.IsIntegerValue())
8046         {
8047           toSetCenter2d = Standard_True;
8048           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
8049         }
8050       }
8051     }
8052     else
8053     {
8054       std::cout << "Syntax error at '" << anArg << "'\n";
8055       return 1;
8056     }
8057   }
8058
8059   // change view parameters in proper order
8060   if (toSetScale)
8061   {
8062     aView->SetScale (aViewScale);
8063   }
8064   if (toSetSize)
8065   {
8066     aView->SetSize (aViewSize);
8067   }
8068   if (toSetEye)
8069   {
8070     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
8071   }
8072   if (toSetAt)
8073   {
8074     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
8075   }
8076   if (toSetProj)
8077   {
8078     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
8079   }
8080   if (toSetUp)
8081   {
8082     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
8083   }
8084   if (toSetCenter2d)
8085   {
8086     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
8087   }
8088
8089   return 0;
8090 }
8091
8092 //==============================================================================
8093 //function : V2DMode
8094 //purpose  :
8095 //==============================================================================
8096 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
8097 {
8098   bool is2dMode = true;
8099   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
8100   if (aV3dView.IsNull())
8101   {
8102     std::cout << "Error: no active view.\n";
8103     return 1;
8104   }
8105   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
8106   {
8107     const TCollection_AsciiString anArg = theArgVec[anArgIt];
8108     TCollection_AsciiString anArgCase = anArg;
8109     anArgCase.LowerCase();
8110     if (anArgIt + 1 < theArgsNb
8111      && anArgCase == "-name")
8112     {
8113       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
8114       TCollection_AsciiString aViewName = aViewNames.GetViewName();
8115       if (!ViewerTest_myViews.IsBound1 (aViewName))
8116       {
8117         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
8118         return 1;
8119       }
8120       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
8121     }
8122     else if (anArgCase == "-mode")
8123     {
8124       if (anArgIt + 1 < theArgsNb
8125        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
8126       {
8127         ++anArgIt;
8128       }
8129     }
8130     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
8131     {
8132       //
8133     }
8134     else
8135     {
8136       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
8137       return 1;
8138     }
8139   }
8140
8141   aV3dView->SetView2DMode (is2dMode);
8142   return 0;
8143 }
8144
8145 //==============================================================================
8146 //function : VAnimation
8147 //purpose  :
8148 //==============================================================================
8149 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
8150                                     Standard_Integer  theArgNb,
8151                                     const char**      theArgVec)
8152 {
8153   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
8154   if (theArgNb < 2)
8155   {
8156     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
8157          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
8158     {
8159       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
8160     }
8161     return 0;
8162   }
8163   if (aCtx.IsNull())
8164   {
8165     std::cout << "Error: no active view\n";
8166     return 1;
8167   }
8168
8169   Standard_Integer anArgIter = 1;
8170   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
8171   if (aNameArg.IsEmpty())
8172   {
8173     std::cout << "Syntax error: animation name is not defined.\n";
8174     return 1;
8175   }
8176
8177   TCollection_AsciiString aNameArgLower = aNameArg;
8178   aNameArgLower.LowerCase();
8179   if (aNameArgLower == "-reset"
8180    || aNameArgLower == "-clear")
8181   {
8182     ViewerTest_AnimationTimelineMap.Clear();
8183     return 0;
8184   }
8185   else if (aNameArg.Value (1) == '-')
8186   {
8187     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
8188     return 1;
8189   }
8190
8191   const char* aNameSplitter = "/";
8192   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
8193   if (aSplitPos == -1)
8194   {
8195     aNameSplitter = ".";
8196     aSplitPos = aNameArg.Search (aNameSplitter);
8197   }
8198
8199   // find existing or create a new animation by specified name within syntax "parent.child".
8200   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8201   for (; !aNameArg.IsEmpty();)
8202   {
8203     TCollection_AsciiString aNameParent;
8204     if (aSplitPos != -1)
8205     {
8206       if (aSplitPos == aNameArg.Length())
8207       {
8208         std::cout << "Syntax error: animation name is not defined.\n";
8209         return 1;
8210       }
8211
8212       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8213       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8214
8215       aSplitPos = aNameArg.Search (aNameSplitter);
8216     }
8217     else
8218     {
8219       aNameParent = aNameArg;
8220       aNameArg.Clear();
8221     }
8222
8223     if (anAnimation.IsNull())
8224     {
8225       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8226       {
8227         anAnimation = new AIS_Animation (aNameParent);
8228         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8229       }
8230       aRootAnimation = anAnimation;
8231     }
8232     else
8233     {
8234       aParentAnimation = anAnimation;
8235       anAnimation = aParentAnimation->Find (aNameParent);
8236       if (anAnimation.IsNull())
8237       {
8238         anAnimation = new AIS_Animation (aNameParent);
8239         aParentAnimation->Add (anAnimation);
8240       }
8241     }
8242   }
8243
8244   if (anArgIter >= theArgNb)
8245   {
8246     // just print the list of children
8247     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8248     {
8249       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8250     }
8251     return 0;
8252   }
8253
8254   // animation parameters
8255   Standard_Boolean toPlay = Standard_False;
8256   Standard_Real aPlaySpeed     = 1.0;
8257   Standard_Real aPlayStartTime = anAnimation->StartPts();
8258   Standard_Real aPlayDuration  = anAnimation->Duration();
8259   Standard_Boolean isFreeCamera = Standard_False;
8260   Standard_Boolean isLockLoop   = Standard_False;
8261
8262   // video recording parameters
8263   TCollection_AsciiString aRecFile;
8264   Image_VideoParams aRecParams;
8265
8266   Handle(V3d_View) aView = ViewerTest::CurrentView();
8267   for (; anArgIter < theArgNb; ++anArgIter)
8268   {
8269     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8270     anArg.LowerCase();
8271     // general options
8272     if (anArg == "-reset"
8273      || anArg == "-clear")
8274     {
8275       anAnimation->Clear();
8276     }
8277     else if (anArg == "-remove"
8278           || anArg == "-del"
8279           || anArg == "-delete")
8280     {
8281       if (!aParentAnimation.IsNull())
8282       {
8283         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8284       }
8285       else
8286       {
8287         aParentAnimation->Remove (anAnimation);
8288       }
8289     }
8290     // playback options
8291     else if (anArg == "-play")
8292     {
8293       toPlay = Standard_True;
8294       if (++anArgIter < theArgNb)
8295       {
8296         if (*theArgVec[anArgIter] == '-')
8297         {
8298           --anArgIter;
8299           continue;
8300         }
8301         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8302
8303         if (++anArgIter < theArgNb)
8304         {
8305           if (*theArgVec[anArgIter] == '-')
8306           {
8307             --anArgIter;
8308             continue;
8309           }
8310           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8311         }
8312       }
8313     }
8314     else if (anArg == "-resume")
8315     {
8316       toPlay = Standard_True;
8317       aPlayStartTime = anAnimation->ElapsedTime();
8318       if (++anArgIter < theArgNb)
8319       {
8320         if (*theArgVec[anArgIter] == '-')
8321         {
8322           --anArgIter;
8323           continue;
8324         }
8325
8326         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8327       }
8328     }
8329     else if (anArg == "-playspeed"
8330           || anArg == "-speed")
8331     {
8332       if (++anArgIter >= theArgNb)
8333       {
8334         std::cout << "Syntax error at " << anArg << ".\n";
8335         return 1;
8336       }
8337       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8338     }
8339     else if (anArg == "-lock"
8340           || anArg == "-lockloop"
8341           || anArg == "-playlockloop")
8342     {
8343       isLockLoop = Standard_True;
8344     }
8345     else if (anArg == "-freecamera"
8346           || anArg == "-playfreecamera"
8347           || anArg == "-freelook")
8348     {
8349       isFreeCamera = Standard_True;
8350     }
8351     // video recodring options
8352     else if (anArg == "-rec"
8353           || anArg == "-record")
8354     {
8355       if (++anArgIter >= theArgNb)
8356       {
8357         std::cout << "Syntax error at " << anArg << ".\n";
8358         return 1;
8359       }
8360
8361       aRecFile = theArgVec[anArgIter];
8362       if (aRecParams.FpsNum <= 0)
8363       {
8364         aRecParams.FpsNum = 24;
8365       }
8366
8367       if (anArgIter + 2 < theArgNb
8368       && *theArgVec[anArgIter + 1] != '-'
8369       && *theArgVec[anArgIter + 2] != '-')
8370       {
8371         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8372         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8373         if (aWidthArg .IsIntegerValue()
8374          && aHeightArg.IsIntegerValue())
8375         {
8376           aRecParams.Width  = aWidthArg .IntegerValue();
8377           aRecParams.Height = aHeightArg.IntegerValue();
8378           anArgIter += 2;
8379         }
8380       }
8381     }
8382     else if (anArg == "-fps")
8383     {
8384       if (++anArgIter >= theArgNb)
8385       {
8386         std::cout << "Syntax error at " << anArg << ".\n";
8387         return 1;
8388       }
8389
8390       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8391       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8392       if (aSplitIndex == 0)
8393       {
8394         aRecParams.FpsNum = aFpsArg.IntegerValue();
8395       }
8396       else
8397       {
8398         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8399         aFpsArg.Split (aFpsArg.Length() - 1);
8400         const TCollection_AsciiString aNumStr = aFpsArg;
8401         aRecParams.FpsNum = aNumStr.IntegerValue();
8402         aRecParams.FpsDen = aDenStr.IntegerValue();
8403         if (aRecParams.FpsDen < 1)
8404         {
8405           std::cout << "Syntax error at " << anArg << ".\n";
8406           return 1;
8407         }
8408       }
8409     }
8410     else if (anArg == "-format")
8411     {
8412       if (++anArgIter >= theArgNb)
8413       {
8414         std::cout << "Syntax error at " << anArg << ".\n";
8415         return 1;
8416       }
8417       aRecParams.Format = theArgVec[anArgIter];
8418     }
8419     else if (anArg == "-pix_fmt"
8420           || anArg == "-pixfmt"
8421           || anArg == "-pixelformat")
8422     {
8423       if (++anArgIter >= theArgNb)
8424       {
8425         std::cout << "Syntax error at " << anArg << ".\n";
8426         return 1;
8427       }
8428       aRecParams.PixelFormat = theArgVec[anArgIter];
8429     }
8430     else if (anArg == "-codec"
8431           || anArg == "-vcodec"
8432           || anArg == "-videocodec")
8433     {
8434       if (++anArgIter >= theArgNb)
8435       {
8436         std::cout << "Syntax error at " << anArg << ".\n";
8437         return 1;
8438       }
8439       aRecParams.VideoCodec = theArgVec[anArgIter];
8440     }
8441     else if (anArg == "-crf"
8442           || anArg == "-preset"
8443           || anArg == "-qp")
8444     {
8445       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8446       if (++anArgIter >= theArgNb)
8447       {
8448         std::cout << "Syntax error at " << anArg << ".\n";
8449         return 1;
8450       }
8451
8452       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8453     }
8454     // animation definition options
8455     else if (anArg == "-start"
8456           || anArg == "-starttime"
8457           || anArg == "-startpts")
8458     {
8459       if (++anArgIter >= theArgNb)
8460       {
8461         std::cout << "Syntax error at " << anArg << ".\n";
8462         return 1;
8463       }
8464
8465       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8466       aRootAnimation->UpdateTotalDuration();
8467     }
8468     else if (anArg == "-end"
8469           || anArg == "-endtime"
8470           || anArg == "-endpts")
8471     {
8472       if (++anArgIter >= theArgNb)
8473       {
8474         std::cout << "Syntax error at " << anArg << ".\n";
8475         return 1;
8476       }
8477
8478       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8479       aRootAnimation->UpdateTotalDuration();
8480     }
8481     else if (anArg == "-dur"
8482           || anArg == "-duration")
8483     {
8484       if (++anArgIter >= theArgNb)
8485       {
8486         std::cout << "Syntax error at " << anArg << ".\n";
8487         return 1;
8488       }
8489
8490       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8491       aRootAnimation->UpdateTotalDuration();
8492     }
8493     else if (anArg == "-command"
8494           || anArg == "-cmd"
8495           || anArg == "-invoke"
8496           || anArg == "-eval"
8497           || anArg == "-proc")
8498     {
8499       if (++anArgIter >= theArgNb)
8500       {
8501         std::cout << "Syntax error at " << anArg << ".\n";
8502         return 1;
8503       }
8504
8505       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8506       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8507     }
8508     else if (anArg == "-objecttrsf"
8509           || anArg == "-objectransformation"
8510           || anArg == "-objtransformation"
8511           || anArg == "-objtrsf"
8512           || anArg == "-object"
8513           || anArg == "-obj")
8514     {
8515       if (++anArgIter >= theArgNb)
8516       {
8517         std::cout << "Syntax error at " << anArg << ".\n";
8518         return 1;
8519       }
8520
8521       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8522       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8523       Handle(AIS_InteractiveObject) anObject;
8524       if (!aMapOfAIS.Find2 (anObjName, anObject))
8525       {
8526         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8527         return 1;
8528       }
8529
8530       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8531       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8532       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8533       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8534       Standard_Boolean isTrsfSet = Standard_False;
8535       Standard_Integer aTrsfArgIter = anArgIter + 1;
8536       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8537       {
8538         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8539         aTrsfArg.LowerCase();
8540         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8541         if (aTrsfArg.StartsWith ("-rotation")
8542          || aTrsfArg.StartsWith ("-rot"))
8543         {
8544           isTrsfSet = Standard_True;
8545           if (aTrsfArgIter + 4 >= theArgNb
8546           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8547           {
8548             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8549             return 1;
8550           }
8551           aTrsfArgIter += 4;
8552         }
8553         else if (aTrsfArg.StartsWith ("-location")
8554               || aTrsfArg.StartsWith ("-loc"))
8555         {
8556           isTrsfSet = Standard_True;
8557           if (aTrsfArgIter + 3 >= theArgNb
8558           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8559           {
8560             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8561             return 1;
8562           }
8563           aTrsfArgIter += 3;
8564         }
8565         else if (aTrsfArg.StartsWith ("-scale"))
8566         {
8567           isTrsfSet = Standard_True;
8568           if (++aTrsfArgIter >= theArgNb)
8569           {
8570             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8571             return 1;
8572           }
8573
8574           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8575           if (!aScaleStr.IsRealValue())
8576           {
8577             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8578             return 1;
8579           }
8580           aScales[anIndex] = aScaleStr.RealValue();
8581         }
8582         else
8583         {
8584           anArgIter = aTrsfArgIter - 1;
8585           break;
8586         }
8587       }
8588       if (!isTrsfSet)
8589       {
8590         std::cout << "Syntax error at " << anArg << ".\n";
8591         return 1;
8592       }
8593       else if (aTrsfArgIter >= theArgNb)
8594       {
8595         anArgIter = theArgNb;
8596       }
8597
8598       aTrsfs[0].SetRotation        (aRotQuats[0]);
8599       aTrsfs[1].SetRotation        (aRotQuats[1]);
8600       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8601       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8602       aTrsfs[0].SetScaleFactor     (aScales[0]);
8603       aTrsfs[1].SetScaleFactor     (aScales[1]);
8604
8605       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8606       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8607     }
8608     else if (anArg == "-viewtrsf"
8609           || anArg == "-view")
8610     {
8611       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8612       if (aCamAnimation.IsNull())
8613       {
8614         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8615         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8616       }
8617
8618       Handle(Graphic3d_Camera) aCams[2] =
8619       {
8620         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8621         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8622       };
8623
8624       Standard_Boolean isTrsfSet = Standard_False;
8625       Standard_Integer aViewArgIter = anArgIter + 1;
8626       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8627       {
8628         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8629         aViewArg.LowerCase();
8630         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8631         if (aViewArg.StartsWith ("-scale"))
8632         {
8633           isTrsfSet = Standard_True;
8634           if (++aViewArgIter >= theArgNb)
8635           {
8636             std::cout << "Syntax error at " << anArg << ".\n";
8637             return 1;
8638           }
8639
8640           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8641           if (!aScaleStr.IsRealValue())
8642           {
8643             std::cout << "Syntax error at " << aViewArg << ".\n";
8644             return 1;
8645           }
8646           Standard_Real aScale = aScaleStr.RealValue();
8647           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8648           aCams[anIndex]->SetScale (aScale);
8649         }
8650         else if (aViewArg.StartsWith ("-eye")
8651               || aViewArg.StartsWith ("-center")
8652               || aViewArg.StartsWith ("-at")
8653               || aViewArg.StartsWith ("-up"))
8654         {
8655           isTrsfSet = Standard_True;
8656           gp_XYZ anXYZ;
8657           if (aViewArgIter + 3 >= theArgNb
8658           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8659           {
8660             std::cout << "Syntax error at " << aViewArg << ".\n";
8661             return 1;
8662           }
8663           aViewArgIter += 3;
8664
8665           if (aViewArg.StartsWith ("-eye"))
8666           {
8667             aCams[anIndex]->SetEye (anXYZ);
8668           }
8669           else if (aViewArg.StartsWith ("-center")
8670                 || aViewArg.StartsWith ("-at"))
8671           {
8672             aCams[anIndex]->SetCenter (anXYZ);
8673           }
8674           else if (aViewArg.StartsWith ("-up"))
8675           {
8676             aCams[anIndex]->SetUp (anXYZ);
8677           }
8678         }
8679         else
8680         {
8681           anArgIter = aViewArgIter - 1;
8682           break;
8683         }
8684       }
8685       if (!isTrsfSet)
8686       {
8687         std::cout << "Syntax error at " << anArg << ".\n";
8688         return 1;
8689       }
8690       else if (aViewArgIter >= theArgNb)
8691       {
8692         anArgIter = theArgNb;
8693       }
8694
8695       aCamAnimation->SetCameraStart(aCams[0]);
8696       aCamAnimation->SetCameraEnd  (aCams[1]);
8697     }
8698     else
8699     {
8700       std::cout << "Syntax error at " << anArg << ".\n";
8701       return 1;
8702     }
8703   }
8704
8705   if (!toPlay && aRecFile.IsEmpty())
8706   {
8707     return 0;
8708   }
8709
8710   // Start animation timeline and process frame updating.
8711   TheIsAnimating = Standard_True;
8712   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8713   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8714   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8715   if (isFreeCamera)
8716   {
8717     aView->Camera()->Copy (aCameraBack);
8718   }
8719
8720   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8721   if (aRecParams.FpsNum <= 0)
8722   {
8723     while (!anAnimation->IsStopped())
8724     {
8725       aCameraBack->Copy (aView->Camera());
8726       const Standard_Real aPts = anAnimation->UpdateTimer();
8727       if (isFreeCamera)
8728       {
8729         aView->Camera()->Copy (aCameraBack);
8730       }
8731
8732       if (aPts >= anUpperPts)
8733       {
8734         anAnimation->Pause();
8735         break;
8736       }
8737
8738       if (aView->IsInvalidated())
8739       {
8740         aView->Redraw();
8741       }
8742       else
8743       {
8744         aView->RedrawImmediate();
8745       }
8746
8747       if (!isLockLoop)
8748       {
8749         // handle user events
8750         theDI.Eval ("after 1 set waiter 1");
8751         theDI.Eval ("vwait waiter");
8752       }
8753       if (!TheIsAnimating)
8754       {
8755         anAnimation->Pause();
8756         theDI << aPts;
8757         break;
8758       }
8759     }
8760
8761     if (aView->IsInvalidated())
8762     {
8763       aView->Redraw();
8764     }
8765     else
8766     {
8767       aView->RedrawImmediate();
8768     }
8769   }
8770   else
8771   {
8772     OSD_Timer aPerfTimer;
8773     aPerfTimer.Start();
8774
8775     Handle(Image_VideoRecorder) aRecorder;
8776     ImageFlipper aFlipper;
8777     Handle(Draw_ProgressIndicator) aProgress;
8778     if (!aRecFile.IsEmpty())
8779     {
8780       if (aRecParams.Width  <= 0
8781        || aRecParams.Height <= 0)
8782       {
8783         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8784       }
8785
8786       aRecorder = new Image_VideoRecorder();
8787       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8788       {
8789         std::cout << "Error: failed to open video file for recording\n";
8790         return 0;
8791       }
8792
8793       aProgress = new Draw_ProgressIndicator (theDI, 1);
8794     }
8795
8796     // Manage frame-rated animation here
8797     Standard_Real aPts = aPlayStartTime;
8798     int64_t aNbFrames = 0;
8799     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8800     Standard_Integer aSecondsProgress = 0;
8801     for (; aPts <= anUpperPts && aPSentry.More();)
8802     {
8803       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8804       aPts = aPlayStartTime + aRecPts;
8805       ++aNbFrames;
8806       if (!anAnimation->Update (aPts))
8807       {
8808         break;
8809       }
8810
8811       if (!aRecorder.IsNull())
8812       {
8813         V3d_ImageDumpOptions aDumpParams;
8814         aDumpParams.Width          = aRecParams.Width;
8815         aDumpParams.Height         = aRecParams.Height;
8816         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8817         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8818         aDumpParams.ToAdjustAspect = Standard_True;
8819         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8820         {
8821           std::cout << "Error: view dump is failed!\n";
8822           return 0;
8823         }
8824         aFlipper.FlipY (aRecorder->ChangeFrame());
8825         if (!aRecorder->PushFrame())
8826         {
8827           return 0;
8828         }
8829       }
8830       else
8831       {
8832         aView->Redraw();
8833       }
8834
8835       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8836       {
8837         aPSentry.Next();
8838         ++aSecondsProgress;
8839       }
8840     }
8841
8842     aPerfTimer.Stop();
8843     anAnimation->Stop();
8844     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8845     theDI << "Average FPS: " << aRecFps << "\n"
8846           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8847
8848     aView->Redraw();
8849   }
8850
8851   aView->SetImmediateUpdate (wasImmediateUpdate);
8852   TheIsAnimating = Standard_False;
8853   return 0;
8854 }
8855
8856
8857 //=======================================================================
8858 //function : VChangeSelected
8859 //purpose  : Adds the shape to selection or remove one from it
8860 //=======================================================================
8861 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8862                                 Standard_Integer argc,
8863                                 const char ** argv)
8864 {
8865   if(argc != 2)
8866   {
8867     di<<"Usage : " << argv[0] << " shape \n";
8868     return 1;
8869   }
8870   //get AIS_Shape:
8871   TCollection_AsciiString aName(argv[1]);
8872   Handle(AIS_InteractiveObject) anAISObject;
8873   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8874     || anAISObject.IsNull())
8875   {
8876     di<<"Use 'vdisplay' before";
8877     return 1;
8878   }
8879
8880   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8881   return 0;
8882 }
8883
8884 //=======================================================================
8885 //function : VNbSelected
8886 //purpose  : Returns number of selected objects
8887 //=======================================================================
8888 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8889                                 Standard_Integer argc,
8890                                 const char ** argv)
8891 {
8892   if(argc != 1)
8893   {
8894     di << "Usage : " << argv[0] << "\n";
8895     return 1;
8896   }
8897   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8898   if(aContext.IsNull())
8899   {
8900     di << "use 'vinit' command before " << argv[0] << "\n";
8901     return 1;
8902   }
8903   di << aContext->NbSelected() << "\n";
8904   return 0;
8905 }
8906
8907 //=======================================================================
8908 //function : VPurgeDisplay
8909 //purpose  : Switches altialiasing on or off
8910 //=======================================================================
8911 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8912                                 Standard_Integer argc,
8913                                 const char ** argv)
8914 {
8915   if (argc > 1)
8916   {
8917     di << "Usage : " << argv[0] << "\n";
8918     return 1;
8919   }
8920   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8921   if (aContext.IsNull())
8922   {
8923     di << "use 'vinit' command before " << argv[0] << "\n";
8924     return 1;
8925   }
8926
8927   di << aContext->PurgeDisplay() << "\n";
8928   return 0;
8929 }
8930
8931 //=======================================================================
8932 //function : VSetViewSize
8933 //purpose  :
8934 //=======================================================================
8935 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8936                                 Standard_Integer argc,
8937                                 const char ** argv)
8938 {
8939   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8940   if(aContext.IsNull())
8941   {
8942     di << "use 'vinit' command before " << argv[0] << "\n";
8943     return 1;
8944   }
8945   if(argc != 2)
8946   {
8947     di<<"Usage : " << argv[0] << " Size\n";
8948     return 1;
8949   }
8950   Standard_Real aSize = Draw::Atof (argv[1]);
8951   if (aSize <= 0.)
8952   {
8953     di<<"Bad Size value  : " << aSize << "\n";
8954     return 1;
8955   }
8956
8957   Handle(V3d_View) aView = ViewerTest::CurrentView();
8958   aView->SetSize(aSize);
8959   return 0;
8960 }
8961
8962 //=======================================================================
8963 //function : VMoveView
8964 //purpose  :
8965 //=======================================================================
8966 static Standard_Integer VMoveView (Draw_Interpretor& di,
8967                                 Standard_Integer argc,
8968                                 const char ** argv)
8969 {
8970   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8971   if(aContext.IsNull())
8972   {
8973     di << "use 'vinit' command before " << argv[0] << "\n";
8974     return 1;
8975   }
8976   if(argc < 4 || argc > 5)
8977   {
8978     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8979     return 1;
8980   }
8981   Standard_Real Dx = Draw::Atof (argv[1]);
8982   Standard_Real Dy = Draw::Atof (argv[2]);
8983   Standard_Real Dz = Draw::Atof (argv[3]);
8984   Standard_Boolean aStart = Standard_True;
8985   if (argc == 5)
8986   {
8987       aStart = (Draw::Atoi (argv[4]) > 0);
8988   }
8989
8990   Handle(V3d_View) aView = ViewerTest::CurrentView();
8991   aView->Move(Dx,Dy,Dz,aStart);
8992   return 0;
8993 }
8994
8995 //=======================================================================
8996 //function : VTranslateView
8997 //purpose  :
8998 //=======================================================================
8999 static Standard_Integer VTranslateView (Draw_Interpretor& di,
9000                                 Standard_Integer argc,
9001                                 const char ** argv)
9002 {
9003   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9004   if(aContext.IsNull())
9005   {
9006     di << "use 'vinit' command before " << argv[0] << "\n";
9007     return 1;
9008   }
9009   if(argc < 4 || argc > 5)
9010   {
9011     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
9012     return 1;
9013   }
9014   Standard_Real Dx = Draw::Atof (argv[1]);
9015   Standard_Real Dy = Draw::Atof (argv[2]);
9016   Standard_Real Dz = Draw::Atof (argv[3]);
9017   Standard_Boolean aStart = Standard_True;
9018   if (argc == 5)
9019   {
9020       aStart = (Draw::Atoi (argv[4]) > 0);
9021   }
9022
9023   Handle(V3d_View) aView = ViewerTest::CurrentView();
9024   aView->Translate(Dx,Dy,Dz,aStart);
9025   return 0;
9026 }
9027
9028 //=======================================================================
9029 //function : VTurnView
9030 //purpose  :
9031 //=======================================================================
9032 static Standard_Integer VTurnView (Draw_Interpretor& di,
9033                                 Standard_Integer argc,
9034                                 const char ** argv)
9035 {
9036   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
9037   if(aContext.IsNull()) {
9038     di << "use 'vinit' command before " << argv[0] << "\n";
9039     return 1;
9040   }
9041   if(argc < 4 || argc > 5){
9042     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
9043     return 1;
9044   }
9045   Standard_Real Ax = Draw::Atof (argv[1]);
9046   Standard_Real Ay = Draw::Atof (argv[2]);
9047   Standard_Real Az = Draw::Atof (argv[3]);
9048   Standard_Boolean aStart = Standard_True;
9049   if (argc == 5)
9050   {
9051       aStart = (Draw::Atoi (argv[4]) > 0);
9052   }
9053
9054   Handle(V3d_View) aView = ViewerTest::CurrentView();
9055   aView->Turn(Ax,Ay,Az,aStart);
9056   return 0;
9057 }
9058
9059 //==============================================================================
9060 //function : VTextureEnv
9061 //purpose  : ENables or disables environment mapping
9062 //==============================================================================
9063 class OCC_TextureEnv : public Graphic3d_TextureEnv
9064 {
9065 public:
9066   OCC_TextureEnv(const Standard_CString FileName);
9067   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
9068   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
9069                             const Standard_Boolean theModulateFlag,
9070                             const Graphic3d_TypeOfTextureFilter theFilter,
9071                             const Standard_ShortReal theXScale,
9072                             const Standard_ShortReal theYScale,
9073                             const Standard_ShortReal theXShift,
9074                             const Standard_ShortReal theYShift,
9075                             const Standard_ShortReal theAngle);
9076   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
9077 };
9078 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
9079
9080 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
9081   : Graphic3d_TextureEnv(theFileName)
9082 {
9083 }
9084
9085 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
9086   : Graphic3d_TextureEnv(theTexId)
9087 {
9088 }
9089
9090 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
9091                                           const Standard_Boolean theModulateFlag,
9092                                           const Graphic3d_TypeOfTextureFilter theFilter,
9093                                           const Standard_ShortReal theXScale,
9094                                           const Standard_ShortReal theYScale,
9095                                           const Standard_ShortReal theXShift,
9096                                           const Standard_ShortReal theYShift,
9097                                           const Standard_ShortReal theAngle)
9098 {
9099   myParams->SetRepeat     (theRepeatFlag);
9100   myParams->SetModulate   (theModulateFlag);
9101   myParams->SetFilter     (theFilter);
9102   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
9103   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
9104   myParams->SetRotation   (theAngle);
9105 }
9106
9107 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
9108 {
9109   // get the active view
9110   Handle(V3d_View) aView = ViewerTest::CurrentView();
9111   if (aView.IsNull())
9112   {
9113     std::cerr << "No active view. Please call vinit.\n";
9114     return 1;
9115   }
9116
9117   // Checking the input arguments
9118   Standard_Boolean anEnableFlag = Standard_False;
9119   Standard_Boolean isOk         = theArgNb >= 2;
9120   if (isOk)
9121   {
9122     TCollection_AsciiString anEnableOpt(theArgVec[1]);
9123     anEnableFlag = anEnableOpt.IsEqual("on");
9124     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
9125   }
9126   if (anEnableFlag)
9127   {
9128     isOk = (theArgNb == 3 || theArgNb == 11);
9129     if (isOk)
9130     {
9131       TCollection_AsciiString aTextureOpt(theArgVec[2]);
9132       isOk = (!aTextureOpt.IsIntegerValue() ||
9133              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
9134
9135       if (isOk && theArgNb == 11)
9136       {
9137         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
9138                                 aModulateOpt(theArgVec[4]),
9139                                 aFilterOpt  (theArgVec[5]),
9140                                 aSScaleOpt  (theArgVec[6]),
9141                                 aTScaleOpt  (theArgVec[7]),
9142                                 aSTransOpt  (theArgVec[8]),
9143                                 aTTransOpt  (theArgVec[9]),
9144                                 anAngleOpt  (theArgVec[10]);
9145         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
9146                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
9147                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
9148                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
9149                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
9150                 anAngleOpt.IsRealValue());
9151       }
9152     }
9153   }
9154
9155   if (!isOk)
9156   {
9157     std::cerr << "Usage :" << std::endl;
9158     std::cerr << theArgVec[0] << " off" << std::endl;
9159     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;
9160     return 1;
9161   }
9162
9163   if (anEnableFlag)
9164   {
9165     TCollection_AsciiString aTextureOpt(theArgVec[2]);
9166     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
9167                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
9168                                      new OCC_TextureEnv(theArgVec[2]);
9169
9170     if (theArgNb == 11)
9171     {
9172       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
9173       aTexEnv->SetTextureParameters(
9174         aRepeatOpt.  IsEqual("repeat"),
9175         aModulateOpt.IsEqual("modulate"),
9176         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
9177                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
9178                                                                            Graphic3d_TOTF_TRILINEAR,
9179         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
9180         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
9181         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
9182         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
9183         (Standard_ShortReal)Draw::Atof(theArgVec[10])
9184         );
9185     }
9186     aView->SetTextureEnv(aTexEnv);
9187   }
9188   else // Disabling environment mapping
9189   {
9190     Handle(Graphic3d_TextureEnv) aTexture;
9191     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
9192   }
9193
9194   aView->Redraw();
9195   return 0;
9196 }
9197
9198 namespace
9199 {
9200   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9201
9202   //! Remove registered clipping plane from all views and objects.
9203   static void removePlane (MapOfPlanes& theRegPlanes,
9204                            const TCollection_AsciiString& theName)
9205   {
9206     Handle(Graphic3d_ClipPlane) aClipPlane;
9207     if (!theRegPlanes.Find (theName, aClipPlane))
9208     {
9209       std::cout << "Warning: no such plane.\n";
9210       return;
9211     }
9212
9213     theRegPlanes.UnBind (theName);
9214     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9215          anIObjIt.More(); anIObjIt.Next())
9216     {
9217       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9218       aPrs->RemoveClipPlane (aClipPlane);
9219     }
9220
9221     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9222          aViewIt.More(); aViewIt.Next())
9223     {
9224       const Handle(V3d_View)& aView = aViewIt.Key2();
9225       aView->RemoveClipPlane(aClipPlane);
9226     }
9227
9228     ViewerTest::RedrawAllViews();
9229   }
9230 }
9231
9232 //===============================================================================================
9233 //function : VClipPlane
9234 //purpose  :
9235 //===============================================================================================
9236 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9237 {
9238   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9239   static MapOfPlanes aRegPlanes;
9240
9241   if (theArgsNb < 2)
9242   {
9243     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9244     {
9245       theDi << aPlaneIter.Key() << " ";
9246     }
9247     return 0;
9248   }
9249
9250   TCollection_AsciiString aCommand (theArgVec[1]);
9251   aCommand.LowerCase();
9252   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9253   if (anActiveView.IsNull())
9254   {
9255     std::cout << "Error: no active view.\n";
9256     return 1;
9257   }
9258
9259   // print maximum number of planes for current viewer
9260   if (aCommand == "-maxplanes"
9261    || aCommand == "maxplanes")
9262   {
9263     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9264           << " plane slots provided by driver.\n";
9265     return 0;
9266   }
9267
9268   // create / delete plane instance
9269   if (aCommand == "-create"
9270    || aCommand == "create"
9271    || aCommand == "-delete"
9272    || aCommand == "delete"
9273    || aCommand == "-clone"
9274    || aCommand == "clone")
9275   {
9276     if (theArgsNb < 3)
9277     {
9278       std::cout << "Syntax error: plane name is required.\n";
9279       return 1;
9280     }
9281
9282     Standard_Boolean toCreate = aCommand == "-create"
9283                              || aCommand == "create";
9284     Standard_Boolean toClone  = aCommand == "-clone"
9285                              || aCommand == "clone";
9286     Standard_Boolean toDelete = aCommand == "-delete"
9287                              || aCommand == "delete";
9288     TCollection_AsciiString aPlane (theArgVec[2]);
9289
9290     if (toCreate)
9291     {
9292       if (aRegPlanes.IsBound (aPlane))
9293       {
9294         std::cout << "Warning: existing plane has been overridden.\n";
9295         toDelete = true;
9296       }
9297       else
9298       {
9299         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9300         return 0;
9301       }
9302     }
9303     else if (toClone) // toClone
9304     {
9305       if (!aRegPlanes.IsBound (aPlane))
9306       {
9307         std::cout << "Error: no such plane.\n";
9308         return 1;
9309       }
9310       else if (theArgsNb < 4)
9311       {
9312         std::cout << "Syntax error: enter name for new plane.\n";
9313         return 1;
9314       }
9315
9316       TCollection_AsciiString aClone (theArgVec[3]);
9317       if (aRegPlanes.IsBound (aClone))
9318       {
9319         std::cout << "Error: plane name is in use.\n";
9320         return 1;
9321       }
9322
9323       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9324
9325       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9326       return 0;
9327     }
9328
9329     if (toDelete)
9330     {
9331       if (aPlane == "ALL"
9332        || aPlane == "all"
9333        || aPlane == "*")
9334       {
9335         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9336         {
9337           aPlane = aPlaneIter.Key();
9338           removePlane (aRegPlanes, aPlane);
9339           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9340         }
9341       }
9342       else
9343       {
9344         removePlane (aRegPlanes, aPlane);
9345       }
9346     }
9347
9348     if (toCreate)
9349     {
9350       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9351     }
9352     return 0;
9353   }
9354
9355   // set / unset plane command
9356   if (aCommand == "set"
9357    || aCommand == "unset")
9358   {
9359     if (theArgsNb < 5)
9360     {
9361       std::cout << "Syntax error: need more arguments.\n";
9362       return 1;
9363     }
9364
9365     // redirect to new syntax
9366     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9367     anArgVec.SetValue (1, theArgVec[0]);
9368     anArgVec.SetValue (2, theArgVec[2]);
9369     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9370     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9371     {
9372       anArgVec.SetValue (anIt, theArgVec[anIt]);
9373     }
9374
9375     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9376   }
9377
9378   // change plane command
9379   TCollection_AsciiString aPlaneName;
9380   Handle(Graphic3d_ClipPlane) aClipPlane;
9381   Standard_Integer anArgIter = 0;
9382   if (aCommand == "-change"
9383    || aCommand == "change")
9384   {
9385     // old syntax support
9386     if (theArgsNb < 3)
9387     {
9388       std::cout << "Syntax error: need more arguments.\n";
9389       return 1;
9390     }
9391
9392     anArgIter  = 3;
9393     aPlaneName = theArgVec[2];
9394     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9395     {
9396       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9397       return 1;
9398     }
9399   }
9400   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9401   {
9402     anArgIter  = 2;
9403     aPlaneName = theArgVec[1];
9404   }
9405   else
9406   {
9407     anArgIter  = 2;
9408     aPlaneName = theArgVec[1];
9409     aClipPlane = new Graphic3d_ClipPlane();
9410     aRegPlanes.Bind (aPlaneName, aClipPlane);
9411     theDi << "Created new plane " << aPlaneName << ".\n";
9412   }
9413
9414   if (theArgsNb - anArgIter < 1)
9415   {
9416     std::cout << "Syntax error: need more arguments.\n";
9417     return 1;
9418   }
9419
9420   for (; anArgIter < theArgsNb; ++anArgIter)
9421   {
9422     const char**     aChangeArgs   = theArgVec + anArgIter;
9423     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9424     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9425     aChangeArg.LowerCase();
9426
9427     Standard_Boolean toEnable = Standard_True;
9428     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9429     {
9430       aClipPlane->SetOn (toEnable);
9431     }
9432     else if (aChangeArg.StartsWith ("-equation")
9433           || aChangeArg.StartsWith ("equation"))
9434     {
9435       if (aNbChangeArgs < 5)
9436       {
9437         std::cout << "Syntax error: need more arguments.\n";
9438         return 1;
9439       }
9440
9441       Standard_Integer aSubIndex = 1;
9442       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9443       if (aPrefixLen < aChangeArg.Length())
9444       {
9445         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9446         if (!aSubStr.IsIntegerValue()
9447           || aSubStr.IntegerValue() <= 0)
9448         {
9449           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9450           return 1;
9451         }
9452         aSubIndex = aSubStr.IntegerValue();
9453       }
9454
9455       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9456       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9457       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9458       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9459       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9460       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9461       {
9462         if (aSubPln->ChainNextPlane().IsNull())
9463         {
9464           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9465         }
9466         aSubPln = aSubPln->ChainNextPlane();
9467       }
9468       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9469       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9470       anArgIter += 4;
9471     }
9472     else if ((aChangeArg == "-boxinterior"
9473            || aChangeArg == "-boxint"
9474            || aChangeArg == "-box")
9475             && aNbChangeArgs >= 7)
9476     {
9477       Graphic3d_BndBox3d aBndBox;
9478       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9479       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9480       anArgIter += 6;
9481
9482       Standard_Integer aNbSubPlanes = 6;
9483       const Graphic3d_Vec3d aDirArray[6] =
9484       {
9485         Graphic3d_Vec3d (-1, 0, 0),
9486         Graphic3d_Vec3d ( 1, 0, 0),
9487         Graphic3d_Vec3d ( 0,-1, 0),
9488         Graphic3d_Vec3d ( 0, 1, 0),
9489         Graphic3d_Vec3d ( 0, 0,-1),
9490         Graphic3d_Vec3d ( 0, 0, 1),
9491       };
9492       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9493       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9494       {
9495         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9496         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9497         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9498         if (aSubPlaneIter + 1 == aNbSubPlanes)
9499         {
9500           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9501         }
9502         else
9503         {
9504           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9505         }
9506         aSubPln = aSubPln->ChainNextPlane();
9507       }
9508     }
9509     else if (aChangeArg == "-capping"
9510           || aChangeArg == "capping")
9511     {
9512       if (aNbChangeArgs < 2)
9513       {
9514         std::cout << "Syntax error: need more arguments.\n";
9515         return 1;
9516       }
9517
9518       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9519       {
9520         aClipPlane->SetCapping (toEnable);
9521         anArgIter += 1;
9522       }
9523       else
9524       {
9525         // just skip otherwise (old syntax)
9526       }
9527     }
9528     else if (aChangeArg == "-useobjectmaterial"
9529           || aChangeArg == "-useobjectmat"
9530           || aChangeArg == "-useobjmat"
9531           || aChangeArg == "-useobjmaterial")
9532     {
9533       if (aNbChangeArgs < 2)
9534       {
9535         std::cout << "Syntax error: need more arguments.\n";
9536         return 1;
9537       }
9538
9539       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9540       {
9541         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9542         anArgIter += 1;
9543       }
9544     }
9545     else if (aChangeArg == "-useobjecttexture"
9546           || aChangeArg == "-useobjecttex"
9547           || aChangeArg == "-useobjtexture"
9548           || aChangeArg == "-useobjtex")
9549     {
9550       if (aNbChangeArgs < 2)
9551       {
9552         std::cout << "Syntax error: need more arguments.\n";
9553         return 1;
9554       }
9555
9556       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9557       {
9558         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9559         anArgIter += 1;
9560       }
9561     }
9562     else if (aChangeArg == "-useobjectshader"
9563           || aChangeArg == "-useobjshader")
9564     {
9565       if (aNbChangeArgs < 2)
9566       {
9567         std::cout << "Syntax error: need more arguments.\n";
9568         return 1;
9569       }
9570
9571       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9572       {
9573         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9574         anArgIter += 1;
9575       }
9576     }
9577     else if (aChangeArg == "-color"
9578           || aChangeArg == "color")
9579     {
9580       Quantity_Color aColor;
9581       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9582                                                            aChangeArgs + 1,
9583                                                            aColor);
9584       if (aNbParsed == 0)
9585       {
9586         std::cout << "Syntax error: need more arguments.\n";
9587         return 1;
9588       }
9589       aClipPlane->SetCappingColor (aColor);
9590       anArgIter += aNbParsed;
9591     }
9592     else if (aNbChangeArgs >= 1
9593           && (aChangeArg == "-material"
9594            || aChangeArg == "material"))
9595     {
9596       ++anArgIter;
9597       Graphic3d_NameOfMaterial aMatName;
9598       if (!Graphic3d_MaterialAspect::MaterialFromName (aChangeArgs[1], aMatName))
9599       {
9600         std::cout << "Syntax error: unknown material '" << aChangeArgs[1] << "'.\n";
9601         return 1;
9602       }
9603       aClipPlane->SetCappingMaterial (aMatName);
9604     }
9605     else if ((aChangeArg == "-transparency"
9606            || aChangeArg == "-transp")
9607           && aNbChangeArgs >= 2)
9608     {
9609       TCollection_AsciiString aValStr (aChangeArgs[1]);
9610       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9611       if (aValStr.IsRealValue())
9612       {
9613         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9614         aMat.SetTransparency ((float )aValStr.RealValue());
9615         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9616         aClipPlane->SetCappingMaterial (aMat);
9617       }
9618       else
9619       {
9620         aValStr.LowerCase();
9621         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9622         if (aValStr == "opaque")
9623         {
9624           aMode = Graphic3d_AlphaMode_Opaque;
9625         }
9626         else if (aValStr == "mask")
9627         {
9628           aMode = Graphic3d_AlphaMode_Mask;
9629         }
9630         else if (aValStr == "blend")
9631         {
9632           aMode = Graphic3d_AlphaMode_Blend;
9633         }
9634         else if (aValStr == "blendauto")
9635         {
9636           aMode = Graphic3d_AlphaMode_BlendAuto;
9637         }
9638         else
9639         {
9640           std::cout << "Syntax error at '" << aValStr << "'\n";
9641           return 1;
9642         }
9643         anAspect->SetAlphaMode (aMode);
9644         aClipPlane->SetCappingAspect (anAspect);
9645       }
9646       anArgIter += 1;
9647     }
9648     else if (aChangeArg == "-texname"
9649           || aChangeArg == "texname")
9650     {
9651       if (aNbChangeArgs < 2)
9652       {
9653         std::cout << "Syntax error: need more arguments.\n";
9654         return 1;
9655       }
9656
9657       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9658       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9659       if (!aTexture->IsDone())
9660       {
9661         aClipPlane->SetCappingTexture (NULL);
9662       }
9663       else
9664       {
9665         aTexture->EnableModulate();
9666         aTexture->EnableRepeat();
9667         aClipPlane->SetCappingTexture (aTexture);
9668       }
9669       anArgIter += 1;
9670     }
9671     else if (aChangeArg == "-texscale"
9672           || aChangeArg == "texscale")
9673     {
9674       if (aClipPlane->CappingTexture().IsNull())
9675       {
9676         std::cout << "Error: no texture is set.\n";
9677         return 1;
9678       }
9679
9680       if (aNbChangeArgs < 3)
9681       {
9682         std::cout << "Syntax error: need more arguments.\n";
9683         return 1;
9684       }
9685
9686       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9687       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9688       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9689       anArgIter += 2;
9690     }
9691     else if (aChangeArg == "-texorigin"
9692           || aChangeArg == "texorigin") // texture origin
9693     {
9694       if (aClipPlane->CappingTexture().IsNull())
9695       {
9696         std::cout << "Error: no texture is set.\n";
9697         return 1;
9698       }
9699
9700       if (aNbChangeArgs < 3)
9701       {
9702         std::cout << "Syntax error: need more arguments.\n";
9703         return 1;
9704       }
9705
9706       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9707       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9708
9709       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9710       anArgIter += 2;
9711     }
9712     else if (aChangeArg == "-texrotate"
9713           || aChangeArg == "texrotate") // texture rotation
9714     {
9715       if (aClipPlane->CappingTexture().IsNull())
9716       {
9717         std::cout << "Error: no texture is set.\n";
9718         return 1;
9719       }
9720
9721       if (aNbChangeArgs < 2)
9722       {
9723         std::cout << "Syntax error: need more arguments.\n";
9724         return 1;
9725       }
9726
9727       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9728       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9729       anArgIter += 1;
9730     }
9731     else if (aChangeArg == "-hatch"
9732           || aChangeArg == "hatch")
9733     {
9734       if (aNbChangeArgs < 2)
9735       {
9736         std::cout << "Syntax error: need more arguments.\n";
9737         return 1;
9738       }
9739
9740       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9741       aHatchStr.LowerCase();
9742       if (aHatchStr == "on")
9743       {
9744         aClipPlane->SetCappingHatchOn();
9745       }
9746       else if (aHatchStr == "off")
9747       {
9748         aClipPlane->SetCappingHatchOff();
9749       }
9750       else
9751       {
9752         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9753       }
9754       anArgIter += 1;
9755     }
9756     else if (aChangeArg == "-delete"
9757           || aChangeArg == "delete")
9758     {
9759       removePlane (aRegPlanes, aPlaneName);
9760       return 0;
9761     }
9762     else if (aChangeArg == "-set"
9763           || aChangeArg == "-unset"
9764           || aChangeArg == "-setoverrideglobal")
9765     {
9766       // set / unset plane command
9767       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9768       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9769       Standard_Integer anIt = 1;
9770       for (; anIt < aNbChangeArgs; ++anIt)
9771       {
9772         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9773         if (anEntityName.IsEmpty()
9774          || anEntityName.Value (1) == '-')
9775         {
9776           break;
9777         }
9778         else if (!toOverrideGlobal
9779                && ViewerTest_myViews.IsBound1 (anEntityName))
9780         {
9781           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9782           if (toSet)
9783           {
9784             aView->AddClipPlane (aClipPlane);
9785           }
9786           else
9787           {
9788             aView->RemoveClipPlane (aClipPlane);
9789           }
9790           continue;
9791         }
9792         else if (GetMapOfAIS().IsBound2 (anEntityName))
9793         {
9794           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9795           if (toSet)
9796           {
9797             aIObj->AddClipPlane (aClipPlane);
9798           }
9799           else
9800           {
9801             aIObj->RemoveClipPlane (aClipPlane);
9802           }
9803           if (!aIObj->ClipPlanes().IsNull())
9804           {
9805             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9806           }
9807         }
9808         else
9809         {
9810           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9811           return 1;
9812         }
9813       }
9814
9815       if (anIt == 1)
9816       {
9817         // apply to active view
9818         if (toSet)
9819         {
9820           anActiveView->AddClipPlane (aClipPlane);
9821         }
9822         else
9823         {
9824           anActiveView->RemoveClipPlane (aClipPlane);
9825         }
9826       }
9827       else
9828       {
9829         anArgIter = anArgIter + anIt - 1;
9830       }
9831     }
9832     else
9833     {
9834       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9835       return 1;
9836     }
9837   }
9838
9839   ViewerTest::RedrawAllViews();
9840   return 0;
9841 }
9842
9843 //===============================================================================================
9844 //function : VZRange
9845 //purpose  :
9846 //===============================================================================================
9847 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9848 {
9849   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9850
9851   if (aCurrentView.IsNull())
9852   {
9853     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9854     return 1;
9855   }
9856
9857   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9858
9859   if (theArgsNb < 2)
9860   {
9861     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9862     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9863     return 0;
9864   }
9865
9866   if (theArgsNb == 3)
9867   {
9868     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9869     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9870
9871     if (aNewZNear >= aNewZFar)
9872     {
9873       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9874       return 1;
9875     }
9876
9877     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9878     {
9879       std::cout << theArgVec[0] << ": invalid arguments: ";
9880       std::cout << "znear, zfar should be positive for perspective camera.\n";
9881       return 1;
9882     }
9883
9884     aCamera->SetZRange (aNewZNear, aNewZFar);
9885   }
9886   else
9887   {
9888     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9889     return 1;
9890   }
9891
9892   aCurrentView->Redraw();
9893
9894   return 0;
9895 }
9896
9897 //===============================================================================================
9898 //function : VAutoZFit
9899 //purpose  :
9900 //===============================================================================================
9901 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9902 {
9903   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9904
9905   if (aCurrentView.IsNull())
9906   {
9907     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9908     return 1;
9909   }
9910
9911   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9912
9913   if (theArgsNb > 3)
9914   {
9915     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9916     return 1;
9917   }
9918
9919   if (theArgsNb < 2)
9920   {
9921     theDi << "Auto z-fit mode: \n"
9922           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9923           << "Scale: " << aScale << "\n";
9924     return 0;
9925   }
9926
9927   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9928
9929   if (theArgsNb >= 3)
9930   {
9931     aScale = Draw::Atoi (theArgVec[2]);
9932   }
9933
9934   aCurrentView->SetAutoZFitMode (isOn, aScale);
9935   aCurrentView->AutoZFit();
9936   aCurrentView->Redraw();
9937
9938   return 0;
9939 }
9940
9941 //! Auxiliary function to print projection type
9942 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9943 {
9944   switch (theProjType)
9945   {
9946     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9947     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9948     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9949     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9950     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9951   }
9952   return "UNKNOWN";
9953 }
9954
9955 //===============================================================================================
9956 //function : VCamera
9957 //purpose  :
9958 //===============================================================================================
9959 static int VCamera (Draw_Interpretor& theDI,
9960                     Standard_Integer  theArgsNb,
9961                     const char**      theArgVec)
9962 {
9963   Handle(V3d_View) aView = ViewerTest::CurrentView();
9964   if (aView.IsNull())
9965   {
9966     std::cout << "Error: no active view.\n";
9967     return 1;
9968   }
9969
9970   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9971   if (theArgsNb < 2)
9972   {
9973     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9974     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9975     theDI << "Distance:   " << aCamera->Distance() << "\n";
9976     theDI << "IOD:        " << aCamera->IOD() << "\n";
9977     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9978     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9979     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9980     return 0;
9981   }
9982
9983   TCollection_AsciiString aPrsName;
9984   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9985   {
9986     Standard_CString        anArg = theArgVec[anArgIter];
9987     TCollection_AsciiString anArgCase (anArg);
9988     anArgCase.LowerCase();
9989     if (anArgCase == "-proj"
9990      || anArgCase == "-projection"
9991      || anArgCase == "-projtype"
9992      || anArgCase == "-projectiontype")
9993     {
9994       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9995     }
9996     else if (anArgCase == "-ortho"
9997           || anArgCase == "-orthographic")
9998     {
9999       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
10000     }
10001     else if (anArgCase == "-persp"
10002           || anArgCase == "-perspective"
10003           || anArgCase == "-perspmono"
10004           || anArgCase == "-perspectivemono"
10005           || anArgCase == "-mono")
10006     {
10007       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10008     }
10009     else if (anArgCase == "-stereo"
10010           || anArgCase == "-stereoscopic"
10011           || anArgCase == "-perspstereo"
10012           || anArgCase == "-perspectivestereo")
10013     {
10014       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10015     }
10016     else if (anArgCase == "-left"
10017           || anArgCase == "-lefteye"
10018           || anArgCase == "-monoleft"
10019           || anArgCase == "-monolefteye"
10020           || anArgCase == "-perpsleft"
10021           || anArgCase == "-perpslefteye")
10022     {
10023       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
10024     }
10025     else if (anArgCase == "-right"
10026           || anArgCase == "-righteye"
10027           || anArgCase == "-monoright"
10028           || anArgCase == "-monorighteye"
10029           || anArgCase == "-perpsright")
10030     {
10031       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
10032     }
10033     else if (anArgCase == "-dist"
10034           || anArgCase == "-distance")
10035     {
10036       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10037       if (anArgValue != NULL
10038       && *anArgValue != '-')
10039       {
10040         ++anArgIter;
10041         aCamera->SetDistance (Draw::Atof (anArgValue));
10042         continue;
10043       }
10044       theDI << aCamera->Distance() << " ";
10045     }
10046     else if (anArgCase == "-iod")
10047     {
10048       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10049       if (anArgValue != NULL
10050       && *anArgValue != '-')
10051       {
10052         ++anArgIter;
10053         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
10054         continue;
10055       }
10056       theDI << aCamera->IOD() << " ";
10057     }
10058     else if (anArgCase == "-iodtype")
10059     {
10060       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10061       TCollection_AsciiString anValueCase (anArgValue);
10062       anValueCase.LowerCase();
10063       if (anValueCase == "abs"
10064        || anValueCase == "absolute")
10065       {
10066         ++anArgIter;
10067         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
10068         continue;
10069       }
10070       else if (anValueCase == "rel"
10071             || anValueCase == "relative")
10072       {
10073         ++anArgIter;
10074         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
10075         continue;
10076       }
10077       else if (*anArgValue != '-')
10078       {
10079         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
10080         return 1;
10081       }
10082       switch (aCamera->GetIODType())
10083       {
10084         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
10085         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
10086       }
10087     }
10088     else if (anArgCase == "-zfocus")
10089     {
10090       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10091       if (anArgValue != NULL
10092       && *anArgValue != '-')
10093       {
10094         ++anArgIter;
10095         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
10096         continue;
10097       }
10098       theDI << aCamera->ZFocus() << " ";
10099     }
10100     else if (anArgCase == "-zfocustype")
10101     {
10102       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
10103       TCollection_AsciiString anValueCase (anArgValue);
10104       anValueCase.LowerCase();
10105       if (anValueCase == "abs"
10106        || anValueCase == "absolute")
10107       {
10108         ++anArgIter;
10109         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
10110         continue;
10111       }
10112       else if (anValueCase == "rel"
10113             || anValueCase == "relative")
10114       {
10115         ++anArgIter;
10116         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
10117         continue;
10118       }
10119       else if (*anArgValue != '-')
10120       {
10121         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
10122         return 1;
10123       }
10124       switch (aCamera->ZFocusType())
10125       {
10126         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
10127         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
10128       }
10129     }
10130     else if (anArgCase == "-fov"
10131           || anArgCase == "-fovy")
10132     {
10133       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
10134       if (anArgValue != NULL
10135       && *anArgValue != '-')
10136       {
10137         ++anArgIter;
10138         aCamera->SetFOVy (Draw::Atof (anArgValue));
10139         continue;
10140       }
10141       theDI << aCamera->FOVy() << " ";
10142     }
10143     else if (aPrsName.IsEmpty()
10144          && !anArgCase.StartsWith ("-"))
10145     {
10146       aPrsName = anArg;
10147     }
10148     else
10149     {
10150       std::cout << "Error: unknown argument '" << anArg << "'\n";
10151       return 1;
10152     }
10153   }
10154
10155   if (aPrsName.IsEmpty()
10156    || theArgsNb > 2)
10157   {
10158     aView->AutoZFit();
10159     aView->Redraw();
10160   }
10161
10162   if (!aPrsName.IsEmpty())
10163   {
10164     Handle(AIS_CameraFrustum) aCameraFrustum;
10165     if (GetMapOfAIS().IsBound2 (aPrsName))
10166     {
10167       // find existing object
10168       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
10169       if (aCameraFrustum.IsNull())
10170       {
10171         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
10172         return 1;
10173       }
10174     }
10175
10176     if (aCameraFrustum.IsNull())
10177     {
10178       aCameraFrustum = new AIS_CameraFrustum();
10179     }
10180     else
10181     {
10182       // not include displayed object of old camera frustum in the new one.
10183       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
10184       aView->ZFitAll();
10185     }
10186     aCameraFrustum->SetCameraFrustum (aView->Camera());
10187
10188     ViewerTest::Display (aPrsName, aCameraFrustum);
10189   }
10190
10191   return 0;
10192 }
10193
10194 //! Parse stereo output mode
10195 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
10196                                          Graphic3d_StereoMode& theMode)
10197 {
10198   TCollection_AsciiString aFlag (theArg);
10199   aFlag.LowerCase();
10200   if (aFlag == "quadbuffer")
10201   {
10202     theMode = Graphic3d_StereoMode_QuadBuffer;
10203   }
10204   else if (aFlag == "anaglyph")
10205   {
10206     theMode = Graphic3d_StereoMode_Anaglyph;
10207   }
10208   else if (aFlag == "row"
10209         || aFlag == "rowinterlaced")
10210   {
10211     theMode = Graphic3d_StereoMode_RowInterlaced;
10212   }
10213   else if (aFlag == "col"
10214         || aFlag == "colinterlaced"
10215         || aFlag == "columninterlaced")
10216   {
10217     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10218   }
10219   else if (aFlag == "chess"
10220         || aFlag == "chessboard")
10221   {
10222     theMode = Graphic3d_StereoMode_ChessBoard;
10223   }
10224   else if (aFlag == "sbs"
10225         || aFlag == "sidebyside")
10226   {
10227     theMode = Graphic3d_StereoMode_SideBySide;
10228   }
10229   else if (aFlag == "ou"
10230         || aFlag == "overunder")
10231   {
10232     theMode = Graphic3d_StereoMode_OverUnder;
10233   }
10234   else if (aFlag == "pageflip"
10235         || aFlag == "softpageflip")
10236   {
10237     theMode = Graphic3d_StereoMode_SoftPageFlip;
10238   }
10239   else
10240   {
10241     return Standard_False;
10242   }
10243   return Standard_True;
10244 }
10245
10246 //! Parse anaglyph filter
10247 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10248                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10249 {
10250   TCollection_AsciiString aFlag (theArg);
10251   aFlag.LowerCase();
10252   if (aFlag == "redcyansimple")
10253   {
10254     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10255   }
10256   else if (aFlag == "redcyan"
10257         || aFlag == "redcyanoptimized")
10258   {
10259     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10260   }
10261   else if (aFlag == "yellowbluesimple")
10262   {
10263     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10264   }
10265   else if (aFlag == "yellowblue"
10266         || aFlag == "yellowblueoptimized")
10267   {
10268     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10269   }
10270   else if (aFlag == "greenmagenta"
10271         || aFlag == "greenmagentasimple")
10272   {
10273     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10274   }
10275   else
10276   {
10277     return Standard_False;
10278   }
10279   return Standard_True;
10280 }
10281
10282 //==============================================================================
10283 //function : VStereo
10284 //purpose  :
10285 //==============================================================================
10286
10287 static int VStereo (Draw_Interpretor& theDI,
10288                     Standard_Integer  theArgNb,
10289                     const char**      theArgVec)
10290 {
10291   Handle(V3d_View) aView = ViewerTest::CurrentView();
10292   if (theArgNb < 2)
10293   {
10294     if (aView.IsNull())
10295     {
10296       std::cout << "Error: no active viewer!\n";
10297       return 0;
10298     }
10299
10300     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10301     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10302     if (isActive)
10303     {
10304       TCollection_AsciiString aMode;
10305       switch (aView->RenderingParams().StereoMode)
10306       {
10307         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10308         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10309         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10310         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10311         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10312         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10313         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10314         case Graphic3d_StereoMode_Anaglyph  :
10315           aMode = "anaglyph";
10316           switch (aView->RenderingParams().AnaglyphFilter)
10317           {
10318             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10319             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10320             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10321             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10322             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10323             default: break;
10324           }
10325         default: break;
10326       }
10327       theDI << "Mode " << aMode << "\n";
10328     }
10329     return 0;
10330   }
10331
10332   Handle(Graphic3d_Camera) aCamera;
10333   Graphic3d_RenderingParams*   aParams   = NULL;
10334   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10335   if (!aView.IsNull())
10336   {
10337     aParams   = &aView->ChangeRenderingParams();
10338     aMode     = aParams->StereoMode;
10339     aCamera   = aView->Camera();
10340   }
10341
10342   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10343   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10344   {
10345     Standard_CString        anArg = theArgVec[anArgIter];
10346     TCollection_AsciiString aFlag (anArg);
10347     aFlag.LowerCase();
10348     if (anUpdateTool.parseRedrawMode (aFlag))
10349     {
10350       continue;
10351     }
10352     else if (aFlag == "0"
10353           || aFlag == "off")
10354     {
10355       if (++anArgIter < theArgNb)
10356       {
10357         std::cout << "Error: wrong number of arguments!\n";
10358         return 1;
10359       }
10360
10361       if (!aCamera.IsNull()
10362        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10363       {
10364         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10365       }
10366       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10367       return 0;
10368     }
10369     else if (aFlag == "1"
10370           || aFlag == "on")
10371     {
10372       if (++anArgIter < theArgNb)
10373       {
10374         std::cout << "Error: wrong number of arguments!\n";
10375         return 1;
10376       }
10377
10378       if (!aCamera.IsNull())
10379       {
10380         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10381       }
10382       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10383       return 0;
10384     }
10385     else if (aFlag == "-reverse"
10386           || aFlag == "-reversed"
10387           || aFlag == "-swap")
10388     {
10389       Standard_Boolean toEnable = Standard_True;
10390       if (++anArgIter < theArgNb
10391       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10392       {
10393         --anArgIter;
10394       }
10395       aParams->ToReverseStereo = toEnable;
10396     }
10397     else if (aFlag == "-noreverse"
10398           || aFlag == "-noswap")
10399     {
10400       Standard_Boolean toDisable = Standard_True;
10401       if (++anArgIter < theArgNb
10402       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10403       {
10404         --anArgIter;
10405       }
10406       aParams->ToReverseStereo = !toDisable;
10407     }
10408     else if (aFlag == "-mode"
10409           || aFlag == "-stereomode")
10410     {
10411       if (++anArgIter >= theArgNb
10412       || !parseStereoMode (theArgVec[anArgIter], aMode))
10413       {
10414         std::cout << "Error: syntax error at '" << anArg << "'\n";
10415         return 1;
10416       }
10417
10418       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10419       {
10420         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10421       }
10422     }
10423     else if (aFlag == "-anaglyph"
10424           || aFlag == "-anaglyphfilter")
10425     {
10426       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10427       if (++anArgIter >= theArgNb
10428       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10429       {
10430         std::cout << "Error: syntax error at '" << anArg << "'\n";
10431         return 1;
10432       }
10433
10434       aMode = Graphic3d_StereoMode_Anaglyph;
10435       aParams->AnaglyphFilter = aFilter;
10436     }
10437     else if (parseStereoMode (anArg, aMode)) // short syntax
10438     {
10439       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10440       {
10441         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10442       }
10443     }
10444     else
10445     {
10446       std::cout << "Error: syntax error at '" << anArg << "'\n";
10447       return 1;
10448     }
10449   }
10450
10451   if (!aView.IsNull())
10452   {
10453     aParams->StereoMode = aMode;
10454     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10455   }
10456   return 0;
10457 }
10458
10459 //===============================================================================================
10460 //function : VDefaults
10461 //purpose  :
10462 //===============================================================================================
10463 static int VDefaults (Draw_Interpretor& theDi,
10464                       Standard_Integer  theArgsNb,
10465                       const char**      theArgVec)
10466 {
10467   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10468   if (aCtx.IsNull())
10469   {
10470     std::cerr << "No active viewer!\n";
10471     return 1;
10472   }
10473
10474   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10475   if (theArgsNb < 2)
10476   {
10477     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10478     {
10479       theDi << "DeflType:           relative\n"
10480             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10481     }
10482     else
10483     {
10484       theDi << "DeflType:           absolute\n"
10485             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10486     }
10487     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10488     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10489     return 0;
10490   }
10491
10492   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10493   {
10494     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10495     anArg.UpperCase();
10496     if (anArg == "-ABSDEFL"
10497      || anArg == "-ABSOLUTEDEFLECTION"
10498      || anArg == "-DEFL"
10499      || anArg == "-DEFLECTION")
10500     {
10501       if (++anArgIter >= theArgsNb)
10502       {
10503         std::cout << "Error: wrong syntax at " << anArg << "\n";
10504         return 1;
10505       }
10506       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10507       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10508     }
10509     else if (anArg == "-RELDEFL"
10510           || anArg == "-RELATIVEDEFLECTION"
10511           || anArg == "-DEVCOEFF"
10512           || anArg == "-DEVIATIONCOEFF"
10513           || anArg == "-DEVIATIONCOEFFICIENT")
10514     {
10515       if (++anArgIter >= theArgsNb)
10516       {
10517         std::cout << "Error: wrong syntax at " << anArg << "\n";
10518         return 1;
10519       }
10520       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10521       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10522     }
10523     else if (anArg == "-ANGDEFL"
10524           || anArg == "-ANGULARDEFL"
10525           || anArg == "-ANGULARDEFLECTION")
10526     {
10527       if (++anArgIter >= theArgsNb)
10528       {
10529         std::cout << "Error: wrong syntax at " << anArg << "\n";
10530         return 1;
10531       }
10532       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10533       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10534     }
10535     else if (anArg == "-AUTOTR"
10536           || anArg == "-AUTOTRIANG"
10537           || anArg == "-AUTOTRIANGULATION")
10538     {
10539       if (++anArgIter >= theArgsNb)
10540       {
10541         std::cout << "Error: wrong syntax at " << anArg << "\n";
10542         return 1;
10543       }
10544       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10545       aValue.LowerCase();
10546       if (aValue == "on"
10547        || aValue == "1")
10548       {
10549         aDefParams->SetAutoTriangulation (Standard_True);
10550       }
10551       else if (aValue == "off"
10552             || aValue == "0")
10553       {
10554         aDefParams->SetAutoTriangulation (Standard_False);
10555       }
10556     }
10557     else
10558     {
10559       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10560     }
10561   }
10562
10563   return 0;
10564 }
10565
10566 //! Auxiliary method
10567 inline void addLight (const Handle(V3d_Light)& theLightNew,
10568                       const Graphic3d_ZLayerId theLayer,
10569                       const Standard_Boolean   theIsGlobal)
10570 {
10571   if (theLightNew.IsNull())
10572   {
10573     return;
10574   }
10575
10576   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10577   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10578   {
10579     aViewer->AddLight (theLightNew);
10580     if (theIsGlobal)
10581     {
10582       aViewer->SetLightOn (theLightNew);
10583     }
10584     else
10585     {
10586       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10587     }
10588   }
10589   else
10590   {
10591     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10592     if (aSettings.Lights().IsNull())
10593     {
10594       aSettings.SetLights (new Graphic3d_LightSet());
10595     }
10596     aSettings.Lights()->Add (theLightNew);
10597     aViewer->SetZLayerSettings (theLayer, aSettings);
10598   }
10599 }
10600
10601 //! Auxiliary method
10602 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10603 {
10604   TCollection_AsciiString anArgNextCase (theArgNext);
10605   anArgNextCase.UpperCase();
10606   if (anArgNextCase.Length() > 5
10607    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10608   {
10609     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10610   }
10611   else
10612   {
10613     return theArgNext.IntegerValue();
10614   }
10615 }
10616
10617 //===============================================================================================
10618 //function : VLight
10619 //purpose  :
10620 //===============================================================================================
10621 static int VLight (Draw_Interpretor& theDi,
10622                    Standard_Integer  theArgsNb,
10623                    const char**      theArgVec)
10624 {
10625   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10626   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10627   if (aView.IsNull()
10628    || aViewer.IsNull())
10629   {
10630     std::cerr << "No active viewer!\n";
10631     return 1;
10632   }
10633
10634   Standard_Real anXYZ[3]   = {};
10635   Standard_Real anAtten[2] = {};
10636   if (theArgsNb < 2)
10637   {
10638     // print lights info
10639     Standard_Integer aLightId = 0;
10640     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10641     {
10642       Handle(V3d_Light) aLight = aLightIter.Value();
10643       const Quantity_Color aColor = aLight->Color();
10644       theDi << "Light #" << aLightId
10645             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10646             << " [" << aLight->GetId() << "]" << "\n";
10647       switch (aLight->Type())
10648       {
10649         case V3d_AMBIENT:
10650         {
10651           theDi << "  Type:       Ambient\n";
10652           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10653           break;
10654         }
10655         case V3d_DIRECTIONAL:
10656         {
10657           theDi << "  Type:       Directional\n";
10658           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10659           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10660           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10661           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10662           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10663           break;
10664         }
10665         case V3d_POSITIONAL:
10666         {
10667           theDi << "  Type:       Positional\n";
10668           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10669           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10670           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10671           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10672           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10673           aLight->Attenuation (anAtten[0], anAtten[1]);
10674           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10675           break;
10676         }
10677         case V3d_SPOT:
10678         {
10679           theDi << "  Type:       Spot\n";
10680           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10681           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10682           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10683           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10684           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10685           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10686           aLight->Attenuation (anAtten[0], anAtten[1]);
10687           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10688           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10689           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10690           break;
10691         }
10692         default:
10693         {
10694           theDi << "  Type:       UNKNOWN\n";
10695           break;
10696         }
10697       }
10698       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10699     }
10700   }
10701
10702   Handle(V3d_Light) aLightNew;
10703   Handle(V3d_Light) aLightOld;
10704   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10705   Standard_Boolean  isGlobal = Standard_True;
10706   Standard_Boolean  toCreate = Standard_False;
10707   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10708   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10709   {
10710     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10711
10712     TCollection_AsciiString aName, aValue;
10713     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10714     TCollection_AsciiString anArgCase (anArg);
10715     anArgCase.UpperCase();
10716     if (anUpdateTool.parseRedrawMode (anArg))
10717     {
10718       continue;
10719     }
10720
10721     if (anArgCase.IsEqual ("NEW")
10722      || anArgCase.IsEqual ("ADD")
10723      || anArgCase.IsEqual ("CREATE")
10724      || anArgCase.IsEqual ("-NEW")
10725      || anArgCase.IsEqual ("-ADD")
10726      || anArgCase.IsEqual ("-CREATE"))
10727     {
10728       toCreate = Standard_True;
10729     }
10730     else if (anArgCase.IsEqual ("-LAYER")
10731           || anArgCase.IsEqual ("-ZLAYER"))
10732     {
10733       if (++anArgIt >= theArgsNb)
10734       {
10735         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10736         return 1;
10737       }
10738
10739       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10740       aValStr.LowerCase();
10741       if (aValStr == "default"
10742        || aValStr == "def")
10743       {
10744         aLayer = Graphic3d_ZLayerId_Default;
10745       }
10746       else if (aValStr == "top")
10747       {
10748         aLayer = Graphic3d_ZLayerId_Top;
10749       }
10750       else if (aValStr == "topmost")
10751       {
10752         aLayer = Graphic3d_ZLayerId_Topmost;
10753       }
10754       else if (aValStr == "toposd"
10755             || aValStr == "osd")
10756       {
10757         aLayer = Graphic3d_ZLayerId_TopOSD;
10758       }
10759       else if (aValStr == "botosd"
10760             || aValStr == "bottom")
10761       {
10762         aLayer = Graphic3d_ZLayerId_BotOSD;
10763       }
10764       else if (aValStr.IsIntegerValue())
10765       {
10766         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10767       }
10768       else
10769       {
10770         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10771         return 1;
10772       }
10773     }
10774     else if (anArgCase.IsEqual ("GLOB")
10775           || anArgCase.IsEqual ("GLOBAL")
10776           || anArgCase.IsEqual ("-GLOB")
10777           || anArgCase.IsEqual ("-GLOBAL"))
10778     {
10779       isGlobal = Standard_True;
10780     }
10781     else if (anArgCase.IsEqual ("LOC")
10782           || anArgCase.IsEqual ("LOCAL")
10783           || anArgCase.IsEqual ("-LOC")
10784           || anArgCase.IsEqual ("-LOCAL"))
10785     {
10786       isGlobal = Standard_False;
10787     }
10788     else if (anArgCase.IsEqual ("DEF")
10789           || anArgCase.IsEqual ("DEFAULTS")
10790           || anArgCase.IsEqual ("-DEF")
10791           || anArgCase.IsEqual ("-DEFAULTS"))
10792     {
10793       toCreate = Standard_False;
10794       aViewer->SetDefaultLights();
10795     }
10796     else if (anArgCase.IsEqual ("CLR")
10797           || anArgCase.IsEqual ("CLEAR")
10798           || anArgCase.IsEqual ("-CLR")
10799           || anArgCase.IsEqual ("-CLEAR"))
10800     {
10801       toCreate = Standard_False;
10802
10803       TColStd_SequenceOfInteger aLayers;
10804       aViewer->GetAllZLayers (aLayers);
10805       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10806       {
10807         if (aLayeriter.Value() == aLayer
10808          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10809         {
10810           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10811           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10812           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10813           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10814           {
10815             break;
10816           }
10817         }
10818       }
10819
10820       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10821       {
10822         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10823         {
10824           Handle(V3d_Light) aLight = aLightIter.Value();
10825           aViewer->DelLight (aLight);
10826           aLightIter = aView->ActiveLightIterator();
10827         }
10828       }
10829     }
10830     else if (anArgCase.IsEqual ("AMB")
10831           || anArgCase.IsEqual ("AMBIENT")
10832           || anArgCase.IsEqual ("AMBLIGHT"))
10833     {
10834       if (!toCreate)
10835       {
10836         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10837         return 1;
10838       }
10839
10840       addLight (aLightNew, aLayer, isGlobal);
10841       toCreate  = Standard_False;
10842       aLightNew = new V3d_AmbientLight();
10843     }
10844     else if (anArgCase.IsEqual ("DIRECTIONAL")
10845           || anArgCase.IsEqual ("DIRLIGHT"))
10846     {
10847       if (!toCreate)
10848       {
10849         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10850         return 1;
10851       }
10852
10853       addLight (aLightNew, aLayer, isGlobal);
10854       toCreate  = Standard_False;
10855       aLightNew = new V3d_DirectionalLight();
10856     }
10857     else if (anArgCase.IsEqual ("SPOT")
10858           || anArgCase.IsEqual ("SPOTLIGHT"))
10859     {
10860       if (!toCreate)
10861       {
10862         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10863         return 1;
10864       }
10865
10866       addLight (aLightNew, aLayer, isGlobal);
10867       toCreate  = Standard_False;
10868       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10869     }
10870     else if (anArgCase.IsEqual ("POSLIGHT")
10871           || anArgCase.IsEqual ("POSITIONAL"))
10872     {
10873       if (!toCreate)
10874       {
10875         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10876         return 1;
10877       }
10878
10879       addLight (aLightNew, aLayer, isGlobal);
10880       toCreate  = Standard_False;
10881       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10882     }
10883     else if (anArgCase.IsEqual ("CHANGE")
10884           || anArgCase.IsEqual ("-CHANGE"))
10885     {
10886       if (++anArgIt >= theArgsNb)
10887       {
10888         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10889         return 1;
10890       }
10891
10892       addLight (aLightNew, aLayer, isGlobal);
10893       aLightNew.Nullify();
10894       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10895       Standard_Integer aLightIt = 0;
10896       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10897       {
10898         if (aLightIt == aLightId)
10899         {
10900           aLightOld = aLightIter.Value();
10901           break;
10902         }
10903       }
10904
10905       if (aLightOld.IsNull())
10906       {
10907         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10908         return 1;
10909       }
10910     }
10911     else if (anArgCase.IsEqual ("DEL")
10912           || anArgCase.IsEqual ("DELETE")
10913           || anArgCase.IsEqual ("-DEL")
10914           || anArgCase.IsEqual ("-DELETE"))
10915     {
10916       Handle(V3d_Light) aLightDel;
10917       if (++anArgIt >= theArgsNb)
10918       {
10919         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10920         return 1;
10921       }
10922
10923       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10924       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10925       Standard_Integer aLightIt = 0;
10926       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10927       {
10928         aLightDel = aLightIter.Value();
10929         if (aLightIt == aLightDelId)
10930         {
10931           break;
10932         }
10933       }
10934       if (aLightDel.IsNull())
10935       {
10936         continue;
10937       }
10938
10939       TColStd_SequenceOfInteger aLayers;
10940       aViewer->GetAllZLayers (aLayers);
10941       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10942       {
10943         if (aLayeriter.Value() == aLayer
10944          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10945         {
10946           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10947           if (!aSettings.Lights().IsNull())
10948           {
10949             aSettings.Lights()->Remove (aLightDel);
10950             if (aSettings.Lights()->IsEmpty())
10951             {
10952               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10953             }
10954           }
10955           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10956           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10957           {
10958             break;
10959           }
10960         }
10961       }
10962
10963       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10964       {
10965         aViewer->DelLight (aLightDel);
10966       }
10967     }
10968     else if (anArgCase.IsEqual ("COLOR")
10969           || anArgCase.IsEqual ("COLOUR")
10970           || anArgCase.IsEqual ("-COLOR")
10971           || anArgCase.IsEqual ("-COLOUR"))
10972     {
10973       if (++anArgIt >= theArgsNb
10974        || aLightCurr.IsNull())
10975       {
10976         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10977         return 1;
10978       }
10979
10980       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10981       anArgNext.UpperCase();
10982       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10983       aLightCurr->SetColor (aColor);
10984     }
10985     else if (anArgCase.IsEqual ("POS")
10986           || anArgCase.IsEqual ("POSITION")
10987           || anArgCase.IsEqual ("-POS")
10988           || anArgCase.IsEqual ("-POSITION"))
10989     {
10990       if ((anArgIt + 3) >= theArgsNb
10991        || aLightCurr.IsNull()
10992        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10993         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10994       {
10995         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10996         return 1;
10997       }
10998
10999       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11000       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11001       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11002       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
11003     }
11004     else if (anArgCase.IsEqual ("DIR")
11005           || anArgCase.IsEqual ("DIRECTION")
11006           || anArgCase.IsEqual ("-DIR")
11007           || anArgCase.IsEqual ("-DIRECTION"))
11008     {
11009       if ((anArgIt + 3) >= theArgsNb
11010        || aLightCurr.IsNull()
11011        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
11012         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11013       {
11014         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11015         return 1;
11016       }
11017
11018       anXYZ[0] = Atof (theArgVec[++anArgIt]);
11019       anXYZ[1] = Atof (theArgVec[++anArgIt]);
11020       anXYZ[2] = Atof (theArgVec[++anArgIt]);
11021       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
11022     }
11023     else if (anArgCase.IsEqual ("SM")
11024           || anArgCase.IsEqual ("SMOOTHNESS")
11025           || anArgCase.IsEqual ("-SM")
11026           || anArgCase.IsEqual ("-SMOOTHNESS"))
11027     {
11028       if (++anArgIt >= theArgsNb
11029        || aLightCurr.IsNull())
11030       {
11031         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11032         return 1;
11033       }
11034
11035       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11036       if (Abs (aSmoothness) <= ShortRealEpsilon())
11037       {
11038         aLightCurr->SetIntensity (1.f);
11039       }
11040       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
11041       {
11042         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
11043       }
11044       else
11045       {
11046         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
11047         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
11048       }
11049
11050       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
11051       {
11052         aLightCurr->SetSmoothRadius (aSmoothness);
11053       }
11054       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
11055       {
11056         aLightCurr->SetSmoothAngle (aSmoothness);
11057       }
11058     }
11059     else if (anArgCase.IsEqual ("INT")
11060           || anArgCase.IsEqual ("INTENSITY")
11061           || anArgCase.IsEqual ("-INT")
11062           || anArgCase.IsEqual ("-INTENSITY"))
11063     {
11064       if (++anArgIt >= theArgsNb
11065        || aLightCurr.IsNull())
11066       {
11067         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11068         return 1;
11069       }
11070
11071       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11072       aLightCurr->SetIntensity (aIntensity);
11073     }
11074     else if (anArgCase.IsEqual ("ANG")
11075           || anArgCase.IsEqual ("ANGLE")
11076           || anArgCase.IsEqual ("-ANG")
11077           || anArgCase.IsEqual ("-ANGLE"))
11078     {
11079       if (++anArgIt >= theArgsNb
11080        || aLightCurr.IsNull()
11081        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11082       {
11083         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11084         return 1;
11085       }
11086
11087       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
11088       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
11089     }
11090     else if (anArgCase.IsEqual ("CONSTATTEN")
11091           || anArgCase.IsEqual ("CONSTATTENUATION")
11092           || anArgCase.IsEqual ("-CONSTATTEN")
11093           || anArgCase.IsEqual ("-CONSTATTENUATION"))
11094     {
11095       if (++anArgIt >= theArgsNb
11096        || aLightCurr.IsNull()
11097        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11098         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11099       {
11100         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11101         return 1;
11102       }
11103
11104       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11105       anAtten[0] = Atof (theArgVec[anArgIt]);
11106       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11107     }
11108     else if (anArgCase.IsEqual ("LINATTEN")
11109           || anArgCase.IsEqual ("LINEARATTEN")
11110           || anArgCase.IsEqual ("LINEARATTENUATION")
11111           || anArgCase.IsEqual ("-LINATTEN")
11112           || anArgCase.IsEqual ("-LINEARATTEN")
11113           || anArgCase.IsEqual ("-LINEARATTENUATION"))
11114     {
11115       if (++anArgIt >= theArgsNb
11116        || aLightCurr.IsNull()
11117        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
11118         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
11119       {
11120         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11121         return 1;
11122       }
11123
11124       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
11125       anAtten[1] = Atof (theArgVec[anArgIt]);
11126       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
11127     }
11128     else if (anArgCase.IsEqual ("EXP")
11129           || anArgCase.IsEqual ("EXPONENT")
11130           || anArgCase.IsEqual ("SPOTEXP")
11131           || anArgCase.IsEqual ("SPOTEXPONENT")
11132           || anArgCase.IsEqual ("-EXP")
11133           || anArgCase.IsEqual ("-EXPONENT")
11134           || anArgCase.IsEqual ("-SPOTEXP")
11135           || anArgCase.IsEqual ("-SPOTEXPONENT"))
11136     {
11137       if (++anArgIt >= theArgsNb
11138        || aLightCurr.IsNull()
11139        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
11140       {
11141         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11142         return 1;
11143       }
11144
11145       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
11146     }
11147     else if (anArgCase.IsEqual ("HEAD")
11148           || anArgCase.IsEqual ("HEADLIGHT")
11149           || anArgCase.IsEqual ("-HEAD")
11150           || anArgCase.IsEqual ("-HEADLIGHT"))
11151     {
11152       if (aLightCurr.IsNull()
11153        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
11154       {
11155         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
11156         return 1;
11157       }
11158
11159       Standard_Boolean isHeadLight = Standard_True;
11160       if (anArgIt + 1 < theArgsNb
11161        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
11162       {
11163         ++anArgIt;
11164       }
11165       aLightCurr->SetHeadlight (isHeadLight);
11166     }
11167     else
11168     {
11169       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
11170     }
11171   }
11172
11173   addLight (aLightNew, aLayer, isGlobal);
11174   return 0;
11175 }
11176
11177 //! Read Graphic3d_RenderingParams::PerfCounters flag.
11178 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
11179                                             Standard_Boolean& theToReset,
11180                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
11181                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
11182 {
11183   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
11184   TCollection_AsciiString aVal = theValue;
11185   Standard_Boolean toReverse = Standard_False;
11186   if (aVal == "none")
11187   {
11188     theToReset = Standard_True;
11189     return Standard_True;
11190   }
11191   else if (aVal.StartsWith ("-"))
11192   {
11193     toReverse = Standard_True;
11194     aVal = aVal.SubString (2, aVal.Length());
11195   }
11196   else if (aVal.StartsWith ("no"))
11197   {
11198     toReverse = Standard_True;
11199     aVal = aVal.SubString (3, aVal.Length());
11200   }
11201   else if (aVal.StartsWith ("+"))
11202   {
11203     aVal = aVal.SubString (2, aVal.Length());
11204   }
11205   else
11206   {
11207     theToReset = Standard_True;
11208   }
11209
11210   if (     aVal == "fps"
11211         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11212   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11213   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11214   else if (aVal == "structs"
11215         || aVal == "structures"
11216         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11217   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11218   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11219   else if (aVal == "tris"
11220         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11221   else if (aVal == "pnts"
11222         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11223   else if (aVal == "mem"
11224         || aVal == "gpumem"
11225         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11226   else if (aVal == "skipimmediate"
11227         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11228   else if (aVal == "frametime"
11229         || aVal == "frametimers"
11230         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11231   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11232   else if (aVal == "extended"
11233         || aVal == "verbose"
11234         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11235   else if (aVal == "full"
11236         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11237   else
11238   {
11239     return Standard_False;
11240   }
11241
11242   if (toReverse)
11243   {
11244     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11245   }
11246   else
11247   {
11248     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11249   }
11250   return Standard_True;
11251 }
11252
11253 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11254 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11255                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11256 {
11257   TCollection_AsciiString aValue = theValue;
11258   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11259   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11260   Standard_Boolean toReset = Standard_False;
11261   for (;;)
11262   {
11263     Standard_Integer aSplitPos = aValue.Search ("|");
11264     if (aSplitPos <= 0)
11265     {
11266       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11267       {
11268         return Standard_False;
11269       }
11270       if (toReset)
11271       {
11272         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11273       }
11274       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11275       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11276       return Standard_True;
11277     }
11278
11279     if (aSplitPos > 1)
11280     {
11281       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11282       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11283       {
11284         return Standard_False;
11285       }
11286     }
11287     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11288   }
11289 }
11290
11291 //=======================================================================
11292 //function : VRenderParams
11293 //purpose  : Enables/disables rendering features
11294 //=======================================================================
11295
11296 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11297                                        Standard_Integer  theArgNb,
11298                                        const char**      theArgVec)
11299 {
11300   Handle(V3d_View) aView = ViewerTest::CurrentView();
11301   if (aView.IsNull())
11302   {
11303     std::cerr << "Error: no active viewer!\n";
11304     return 1;
11305   }
11306
11307   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11308   TCollection_AsciiString aCmdName (theArgVec[0]);
11309   aCmdName.LowerCase();
11310   if (aCmdName == "vraytrace")
11311   {
11312     if (theArgNb == 1)
11313     {
11314       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11315       return 0;
11316     }
11317     else if (theArgNb == 2)
11318     {
11319       TCollection_AsciiString aValue (theArgVec[1]);
11320       aValue.LowerCase();
11321       if (aValue == "on"
11322        || aValue == "1")
11323       {
11324         aParams.Method = Graphic3d_RM_RAYTRACING;
11325         aView->Redraw();
11326         return 0;
11327       }
11328       else if (aValue == "off"
11329             || aValue == "0")
11330       {
11331         aParams.Method = Graphic3d_RM_RASTERIZATION;
11332         aView->Redraw();
11333         return 0;
11334       }
11335       else
11336       {
11337         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11338         return 1;
11339       }
11340     }
11341     else
11342     {
11343       std::cout << "Error: wrong number of arguments\n";
11344       return 1;
11345     }
11346   }
11347
11348   if (theArgNb < 2)
11349   {
11350     theDI << "renderMode:  ";
11351     switch (aParams.Method)
11352     {
11353       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11354       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11355     }
11356     theDI << "\n";
11357     theDI << "transparency:  ";
11358     switch (aParams.TransparencyMethod)
11359     {
11360       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11361       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11362                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11363     }
11364     theDI << "\n";
11365     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11366     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11367     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11368     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11369     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11370     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11371     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11372     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11373     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11374     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11375     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11376     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11377     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11378     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11379     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11380     theDI << "shadingModel: ";
11381     switch (aView->ShadingModel())
11382     {
11383       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11384       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11385       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11386       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11387       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11388     }
11389     {
11390       theDI << "perfCounters:";
11391       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11392       {
11393         theDI << " fps";
11394       }
11395       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11396       {
11397         theDI << " cpu";
11398       }
11399       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11400       {
11401         theDI << " structs";
11402       }
11403       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11404       {
11405         theDI << " groups";
11406       }
11407       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11408       {
11409         theDI << " arrays";
11410       }
11411       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11412       {
11413         theDI << " tris";
11414       }
11415       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11416       {
11417         theDI << " pnts";
11418       }
11419       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11420       {
11421         theDI << " gpumem";
11422       }
11423       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11424       {
11425         theDI << " frameTime";
11426       }
11427       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11428       {
11429         theDI << " skipimmediate";
11430       }
11431       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11432       {
11433         theDI << " none";
11434       }
11435       theDI << "\n";
11436     }
11437     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11438     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11439     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11440                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11441                                                                                                                     "noUpdate") << "\n";
11442     theDI << "\n";
11443     return 0;
11444   }
11445
11446   Standard_Boolean toPrint = Standard_False;
11447   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11448   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11449   {
11450     Standard_CString        anArg (theArgVec[anArgIter]);
11451     TCollection_AsciiString aFlag (anArg);
11452     aFlag.LowerCase();
11453     if (anUpdateTool.parseRedrawMode (aFlag))
11454     {
11455       continue;
11456     }
11457     else if (aFlag == "-echo"
11458           || aFlag == "-print")
11459     {
11460       toPrint = Standard_True;
11461       anUpdateTool.Invalidate();
11462     }
11463     else if (aFlag == "-mode"
11464           || aFlag == "-rendermode"
11465           || aFlag == "-render_mode")
11466     {
11467       if (toPrint)
11468       {
11469         switch (aParams.Method)
11470         {
11471           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11472           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11473         }
11474         continue;
11475       }
11476       else
11477       {
11478         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11479         return 1;
11480       }
11481     }
11482     else if (aFlag == "-ray"
11483           || aFlag == "-raytrace")
11484     {
11485       if (toPrint)
11486       {
11487         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11488         continue;
11489       }
11490
11491       aParams.Method = Graphic3d_RM_RAYTRACING;
11492     }
11493     else if (aFlag == "-rast"
11494           || aFlag == "-raster"
11495           || aFlag == "-rasterization")
11496     {
11497       if (toPrint)
11498       {
11499         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11500         continue;
11501       }
11502
11503       aParams.Method = Graphic3d_RM_RASTERIZATION;
11504     }
11505     else if (aFlag == "-msaa")
11506     {
11507       if (toPrint)
11508       {
11509         theDI << aParams.NbMsaaSamples << " ";
11510         continue;
11511       }
11512       else if (++anArgIter >= theArgNb)
11513       {
11514         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11515         return 1;
11516       }
11517
11518       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11519       if (aNbSamples < 0)
11520       {
11521         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11522         return 1;
11523       }
11524       else
11525       {
11526         aParams.NbMsaaSamples = aNbSamples;
11527       }
11528     }
11529     else if (aFlag == "-linefeather"
11530           || aFlag == "-edgefeather"
11531           || aFlag == "-feather")
11532     {
11533       if (toPrint)
11534       {
11535         theDI << " " << aParams.LineFeather << " ";
11536         continue;
11537       }
11538       else if (++anArgIter >= theArgNb)
11539       {
11540         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11541         return 1;
11542       }
11543
11544       TCollection_AsciiString aParam = theArgVec[anArgIter];
11545       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11546       if (aFeather <= 0.0f)
11547       {
11548         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11549         return 1;
11550       }
11551       aParams.LineFeather = aFeather;
11552     }
11553     else if (aFlag == "-oit")
11554     {
11555       if (toPrint)
11556       {
11557         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11558         {
11559           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11560         }
11561         else
11562         {
11563           theDI << "off" << " ";
11564         }
11565         continue;
11566       }
11567       else if (++anArgIter >= theArgNb)
11568       {
11569         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11570         return 1;
11571       }
11572
11573       TCollection_AsciiString aParam = theArgVec[anArgIter];
11574       aParam.LowerCase();
11575       if (aParam.IsRealValue())
11576       {
11577         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11578         if (aWeight < 0.f || aWeight > 1.f)
11579         {
11580           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11581           return 1;
11582         }
11583
11584         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11585         aParams.OitDepthFactor     = aWeight;
11586       }
11587       else if (aParam == "off")
11588       {
11589         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11590       }
11591       else
11592       {
11593         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11594         return 1;
11595       }
11596     }
11597     else if (aFlag == "-depthprepass")
11598     {
11599       if (toPrint)
11600       {
11601         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11602         continue;
11603       }
11604       aParams.ToEnableDepthPrepass = Standard_True;
11605       if (anArgIter + 1 < theArgNb
11606        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11607       {
11608         ++anArgIter;
11609       }
11610     }
11611     else if (aFlag == "-samplealphatocoverage"
11612           || aFlag == "-alphatocoverage")
11613     {
11614       if (toPrint)
11615       {
11616         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11617         continue;
11618       }
11619       aParams.ToEnableAlphaToCoverage = Standard_True;
11620       if (anArgIter + 1 < theArgNb
11621        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11622       {
11623         ++anArgIter;
11624       }
11625     }
11626     else if (aFlag == "-rendscale"
11627           || aFlag == "-renderscale"
11628           || aFlag == "-renderresolutionscale")
11629     {
11630       if (toPrint)
11631       {
11632         theDI << aParams.RenderResolutionScale << " ";
11633         continue;
11634       }
11635       else if (++anArgIter >= theArgNb)
11636       {
11637         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11638         return 1;
11639       }
11640
11641       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11642       if (aScale < 0.01)
11643       {
11644         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11645         return 1;
11646       }
11647       else
11648       {
11649         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11650       }
11651     }
11652     else if (aFlag == "-raydepth"
11653           || aFlag == "-ray_depth")
11654     {
11655       if (toPrint)
11656       {
11657         theDI << aParams.RaytracingDepth << " ";
11658         continue;
11659       }
11660       else if (++anArgIter >= theArgNb)
11661       {
11662         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11663         return 1;
11664       }
11665
11666       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11667
11668       // We allow RaytracingDepth be more than 10 in case of GI enabled
11669       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11670       {
11671         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11672         return 1;
11673       }
11674       else
11675       {
11676         aParams.RaytracingDepth = aDepth;
11677       }
11678     }
11679     else if (aFlag == "-shad"
11680           || aFlag == "-shadows")
11681     {
11682       if (toPrint)
11683       {
11684         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11685         continue;
11686       }
11687
11688       Standard_Boolean toEnable = Standard_True;
11689       if (++anArgIter < theArgNb
11690       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11691       {
11692         --anArgIter;
11693       }
11694       aParams.IsShadowEnabled = toEnable;
11695     }
11696     else if (aFlag == "-refl"
11697           || aFlag == "-reflections")
11698     {
11699       if (toPrint)
11700       {
11701         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11702         continue;
11703       }
11704
11705       Standard_Boolean toEnable = Standard_True;
11706       if (++anArgIter < theArgNb
11707       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11708       {
11709         --anArgIter;
11710       }
11711       aParams.IsReflectionEnabled = toEnable;
11712     }
11713     else if (aFlag == "-fsaa")
11714     {
11715       if (toPrint)
11716       {
11717         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11718         continue;
11719       }
11720
11721       Standard_Boolean toEnable = Standard_True;
11722       if (++anArgIter < theArgNb
11723       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11724       {
11725         --anArgIter;
11726       }
11727       aParams.IsAntialiasingEnabled = toEnable;
11728     }
11729     else if (aFlag == "-gleam")
11730     {
11731       if (toPrint)
11732       {
11733         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11734         continue;
11735       }
11736
11737       Standard_Boolean toEnable = Standard_True;
11738       if (++anArgIter < theArgNb
11739       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11740       {
11741         --anArgIter;
11742       }
11743       aParams.IsTransparentShadowEnabled = toEnable;
11744     }
11745     else if (aFlag == "-gi")
11746     {
11747       if (toPrint)
11748       {
11749         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11750         continue;
11751       }
11752
11753       Standard_Boolean toEnable = Standard_True;
11754       if (++anArgIter < theArgNb
11755       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11756       {
11757         --anArgIter;
11758       }
11759       aParams.IsGlobalIlluminationEnabled = toEnable;
11760       if (!toEnable)
11761       {
11762         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11763       }
11764     }
11765     else if (aFlag == "-blockedrng"
11766           || aFlag == "-brng")
11767     {
11768       if (toPrint)
11769       {
11770         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11771         continue;
11772       }
11773
11774       Standard_Boolean toEnable = Standard_True;
11775       if (++anArgIter < theArgNb
11776         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11777       {
11778         --anArgIter;
11779       }
11780       aParams.CoherentPathTracingMode = toEnable;
11781     }
11782     else if (aFlag == "-maxrad")
11783     {
11784       if (toPrint)
11785       {
11786         theDI << aParams.RadianceClampingValue << " ";
11787         continue;
11788       }
11789       else if (++anArgIter >= theArgNb)
11790       {
11791         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11792         return 1;
11793       }
11794
11795       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11796       if (!aMaxRadStr.IsRealValue())
11797       {
11798         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11799         return 1;
11800       }
11801
11802       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11803       if (aMaxRadiance <= 0.0)
11804       {
11805         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11806         return 1;
11807       }
11808       else
11809       {
11810         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11811       }
11812     }
11813     else if (aFlag == "-iss")
11814     {
11815       if (toPrint)
11816       {
11817         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11818         continue;
11819       }
11820
11821       Standard_Boolean toEnable = Standard_True;
11822       if (++anArgIter < theArgNb
11823         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11824       {
11825         --anArgIter;
11826       }
11827       aParams.AdaptiveScreenSampling = toEnable;
11828     }
11829     else if (aFlag == "-issatomic")
11830     {
11831       if (toPrint)
11832       {
11833         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11834         continue;
11835       }
11836
11837       Standard_Boolean toEnable = Standard_True;
11838       if (++anArgIter < theArgNb
11839       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11840       {
11841         --anArgIter;
11842       }
11843       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11844     }
11845     else if (aFlag == "-issd")
11846     {
11847       if (toPrint)
11848       {
11849         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11850         continue;
11851       }
11852
11853       Standard_Boolean toEnable = Standard_True;
11854       if (++anArgIter < theArgNb
11855         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11856       {
11857         --anArgIter;
11858       }
11859       aParams.ShowSamplingTiles = toEnable;
11860     }
11861     else if (aFlag == "-tilesize")
11862     {
11863       if (toPrint)
11864       {
11865         theDI << aParams.RayTracingTileSize << " ";
11866         continue;
11867       }
11868       else if (++anArgIter >= theArgNb)
11869       {
11870         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11871         return 1;
11872       }
11873
11874       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11875       if (aTileSize < 1)
11876       {
11877         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11878         return 1;
11879       }
11880       aParams.RayTracingTileSize = aTileSize;
11881     }
11882     else if (aFlag == "-nbtiles")
11883     {
11884       if (toPrint)
11885       {
11886         theDI << aParams.NbRayTracingTiles << " ";
11887         continue;
11888       }
11889       else if (++anArgIter >= theArgNb)
11890       {
11891         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11892         return 1;
11893       }
11894
11895       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11896       if (aNbTiles < -1)
11897       {
11898         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11899         return 1;
11900       }
11901       else if (aNbTiles > 0
11902             && (aNbTiles < 64
11903              || aNbTiles > 1024))
11904       {
11905         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11906       }
11907       aParams.NbRayTracingTiles = aNbTiles;
11908     }
11909     else if (aFlag == "-env")
11910     {
11911       if (toPrint)
11912       {
11913         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11914         continue;
11915       }
11916
11917       Standard_Boolean toEnable = Standard_True;
11918       if (++anArgIter < theArgNb
11919         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11920       {
11921         --anArgIter;
11922       }
11923       aParams.UseEnvironmentMapBackground = toEnable;
11924     }
11925     else if (aFlag == "-twoside")
11926     {
11927       if (toPrint)
11928       {
11929         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11930         continue;
11931       }
11932
11933       Standard_Boolean toEnable = Standard_True;
11934       if (++anArgIter < theArgNb
11935         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11936       {
11937         --anArgIter;
11938       }
11939       aParams.TwoSidedBsdfModels = toEnable;
11940     }
11941     else if (aFlag == "-shademodel"
11942           || aFlag == "-shadingmodel"
11943           || aFlag == "-shading")
11944     {
11945       if (toPrint)
11946       {
11947         switch (aView->ShadingModel())
11948         {
11949           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11950           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11951           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11952           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11953           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11954         }
11955         continue;
11956       }
11957
11958       if (++anArgIter >= theArgNb)
11959       {
11960         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11961       }
11962
11963       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11964       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11965        && aModel != Graphic3d_TOSM_DEFAULT)
11966       {
11967         aView->SetShadingModel (aModel);
11968       }
11969       else
11970       {
11971         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11972         return 1;
11973       }
11974     }
11975     else if (aFlag == "-resolution")
11976     {
11977       if (++anArgIter >= theArgNb)
11978       {
11979         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11980         return 1;
11981       }
11982
11983       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11984       if (aResolution.IsIntegerValue())
11985       {
11986         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11987       }
11988       else
11989       {
11990         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11991         return 1;
11992       }
11993     }
11994     else if (aFlag == "-rebuildglsl"
11995           || aFlag == "-rebuild")
11996     {
11997       if (toPrint)
11998       {
11999         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
12000         continue;
12001       }
12002
12003       Standard_Boolean toEnable = Standard_True;
12004       if (++anArgIter < theArgNb
12005           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
12006       {
12007         --anArgIter;
12008       }
12009       aParams.RebuildRayTracingShaders = toEnable;
12010     }
12011     else if (aFlag == "-focal")
12012     {
12013       if (++anArgIter >= theArgNb)
12014       {
12015         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12016         return 1;
12017       }
12018
12019       TCollection_AsciiString aParam (theArgVec[anArgIter]);
12020       if (aParam.IsRealValue())
12021       {
12022         float aFocalDist = static_cast<float> (aParam.RealValue());
12023         if (aFocalDist < 0)
12024         {
12025           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12026           return 1;
12027         }
12028         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
12029       }
12030       else
12031       {
12032         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12033         return 1;
12034       }
12035     }
12036     else if (aFlag == "-aperture")
12037     {
12038       if (++anArgIter >= theArgNb)
12039       {
12040         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12041         return 1;
12042       }
12043
12044       TCollection_AsciiString aParam(theArgVec[anArgIter]);
12045       if (aParam.IsRealValue())
12046       {
12047         float aApertureSize = static_cast<float> (aParam.RealValue());
12048         if (aApertureSize < 0)
12049         {
12050           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
12051           return 1;
12052         }
12053         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
12054       }
12055       else
12056       {
12057         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12058         return 1;
12059       }
12060     }
12061     else if (aFlag == "-exposure")
12062     {
12063       if (++anArgIter >= theArgNb)
12064       {
12065         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12066         return 1;
12067       }
12068
12069       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
12070       if (anExposure.IsRealValue())
12071       {
12072         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
12073       }
12074       else
12075       {
12076         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12077         return 1;
12078       }
12079     }
12080     else if (aFlag == "-whitepoint")
12081     {
12082       if (++anArgIter >= theArgNb)
12083       {
12084         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12085         return 1;
12086       }
12087
12088       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
12089       if (aWhitePoint.IsRealValue())
12090       {
12091         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
12092       }
12093       else
12094       {
12095         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12096         return 1;
12097       }
12098     }
12099     else if (aFlag == "-tonemapping")
12100     {
12101       if (++anArgIter >= theArgNb)
12102       {
12103         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12104         return 1;
12105       }
12106
12107       TCollection_AsciiString aMode (theArgVec[anArgIter]);
12108       aMode.LowerCase();
12109
12110       if (aMode == "disabled")
12111       {
12112         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
12113       }
12114       else if (aMode == "filmic")
12115       {
12116         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
12117       }
12118       else
12119       {
12120         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
12121         return 1;
12122       }
12123     }
12124     else if (aFlag == "-performancestats"
12125           || aFlag == "-performancecounters"
12126           || aFlag == "-perfstats"
12127           || aFlag == "-perfcounters"
12128           || aFlag == "-stats")
12129     {
12130       if (++anArgIter >= theArgNb)
12131       {
12132         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12133         return 1;
12134       }
12135
12136       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
12137       aFlagsStr.LowerCase();
12138       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
12139       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
12140       {
12141         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12142         return 1;
12143       }
12144       aView->ChangeRenderingParams().CollectedStats = aFlags;
12145       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
12146     }
12147     else if (aFlag == "-perfupdateinterval"
12148           || aFlag == "-statsupdateinterval")
12149     {
12150       if (++anArgIter >= theArgNb)
12151       {
12152         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12153         return 1;
12154       }
12155       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12156     }
12157     else if (aFlag == "-perfchart"
12158           || aFlag == "-statschart")
12159     {
12160       if (++anArgIter >= theArgNb)
12161       {
12162         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12163         return 1;
12164       }
12165       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
12166     }
12167     else if (aFlag == "-perfchartmax"
12168           || aFlag == "-statschartmax")
12169     {
12170       if (++anArgIter >= theArgNb)
12171       {
12172         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
12173         return 1;
12174       }
12175       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
12176     }
12177     else if (aFlag == "-frustumculling"
12178           || aFlag == "-culling")
12179     {
12180       if (toPrint)
12181       {
12182         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
12183                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
12184                                                                                                    "noUpdate") << " ";
12185         continue;
12186       }
12187
12188       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
12189       if (++anArgIter < theArgNb)
12190       {
12191         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
12192         aStateStr.LowerCase();
12193         bool toEnable = true;
12194         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
12195         {
12196           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
12197         }
12198         else if (aStateStr == "noupdate"
12199               || aStateStr == "freeze")
12200         {
12201           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
12202         }
12203         else
12204         {
12205           --anArgIter;
12206         }
12207       }
12208       aParams.FrustumCullingState = aState;
12209     }
12210     else
12211     {
12212       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12213       return 1;
12214     }
12215   }
12216
12217   return 0;
12218 }
12219
12220 //=======================================================================
12221 //function : searchInfo
12222 //purpose  :
12223 //=======================================================================
12224 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12225                                            const TCollection_AsciiString&              theKey)
12226 {
12227   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12228   {
12229     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12230     {
12231       return anIter.Value();
12232     }
12233   }
12234   return TCollection_AsciiString();
12235 }
12236
12237 //=======================================================================
12238 //function : VStatProfiler
12239 //purpose  :
12240 //=======================================================================
12241 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12242                                        Standard_Integer  theArgNb,
12243                                        const char**      theArgVec)
12244 {
12245   Handle(V3d_View) aView = ViewerTest::CurrentView();
12246   if (aView.IsNull())
12247   {
12248     std::cerr << "Error: no active viewer!\n";
12249     return 1;
12250   }
12251
12252   Standard_Boolean toRedraw = Standard_True;
12253   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12254   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12255   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12256   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12257   {
12258     Standard_CString        anArg (theArgVec[anArgIter]);
12259     TCollection_AsciiString aFlag (anArg);
12260     aFlag.LowerCase();
12261     if (aFlag == "-noredraw")
12262     {
12263       toRedraw = Standard_False;
12264     }
12265     else
12266     {
12267       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12268       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12269       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12270       else if (aFlag == "alllayers"
12271             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12272       else if (aFlag == "allstructs"
12273             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12274       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12275       else if (aFlag == "allarrays"
12276             || aFlag == "fillarrays"
12277             || aFlag == "linearrays"
12278             || aFlag == "pointarrays"
12279             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12280       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12281       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12282       else if (aFlag == "geommem"
12283             || aFlag == "texturemem"
12284             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12285       else if (aFlag == "elapsedframe"
12286             || aFlag == "cpuframeaverage"
12287             || aFlag == "cpupickingaverage"
12288             || aFlag == "cpucullingaverage"
12289             || aFlag == "cpudynaverage"
12290             || aFlag == "cpuframemax"
12291             || aFlag == "cpupickingmax"
12292             || aFlag == "cpucullingmax"
12293             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12294       else
12295       {
12296         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12297         continue;
12298       }
12299
12300       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12301     }
12302   }
12303
12304   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12305   {
12306     aView->ChangeRenderingParams().CollectedStats =
12307       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12308
12309     if (toRedraw)
12310     {
12311       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12312       aView->Redraw();
12313       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12314     }
12315
12316     TColStd_IndexedDataMapOfStringString aDict;
12317     aView->StatisticInformation (aDict);
12318
12319     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12320
12321     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12322     {
12323       Standard_CString        anArg(theArgVec[anArgIter]);
12324       TCollection_AsciiString aFlag(anArg);
12325       aFlag.LowerCase();
12326       if (aFlag == "fps")
12327       {
12328         theDI << searchInfo (aDict, "FPS") << " ";
12329       }
12330       else if (aFlag == "cpu")
12331       {
12332         theDI << searchInfo (aDict, "CPU FPS") << " ";
12333       }
12334       else if (aFlag == "alllayers")
12335       {
12336         theDI << searchInfo (aDict, "Layers") << " ";
12337       }
12338       else if (aFlag == "layers")
12339       {
12340         theDI << searchInfo (aDict, "Rendered layers") << " ";
12341       }
12342       else if (aFlag == "allstructs")
12343       {
12344         theDI << searchInfo (aDict, "Structs") << " ";
12345       }
12346       else if (aFlag == "structs")
12347       {
12348         theDI << searchInfo (aDict, "Rendered structs") << " ";
12349       }
12350       else if (aFlag == "groups")
12351       {
12352         theDI << searchInfo (aDict, "Rendered groups") << " ";
12353       }
12354       else if (aFlag == "allarrays")
12355       {
12356         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12357       }
12358       else if (aFlag == "fillarrays")
12359       {
12360         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12361       }
12362       else if (aFlag == "linearrays")
12363       {
12364         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12365       }
12366       else if (aFlag == "pointarrays")
12367       {
12368         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12369       }
12370       else if (aFlag == "textarrays")
12371       {
12372         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12373       }
12374       else if (aFlag == "triangles")
12375       {
12376         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12377       }
12378       else if (aFlag == "points")
12379       {
12380         theDI << searchInfo (aDict, "Rendered points") << " ";
12381       }
12382       else if (aFlag == "geommem")
12383       {
12384         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12385       }
12386       else if (aFlag == "texturemem")
12387       {
12388         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12389       }
12390       else if (aFlag == "framemem")
12391       {
12392         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12393       }
12394       else if (aFlag == "elapsedframe")
12395       {
12396         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12397       }
12398       else if (aFlag == "cpuframe_average")
12399       {
12400         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12401       }
12402       else if (aFlag == "cpupicking_average")
12403       {
12404         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12405       }
12406       else if (aFlag == "cpuculling_average")
12407       {
12408         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12409       }
12410       else if (aFlag == "cpudyn_average")
12411       {
12412         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12413       }
12414       else if (aFlag == "cpuframe_max")
12415       {
12416         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12417       }
12418       else if (aFlag == "cpupicking_max")
12419       {
12420         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12421       }
12422       else if (aFlag == "cpuculling_max")
12423       {
12424         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12425       }
12426       else if (aFlag == "cpudyn_max")
12427       {
12428         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12429       }
12430     }
12431   }
12432   else
12433   {
12434     if (toRedraw)
12435     {
12436       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12437       aView->Redraw();
12438       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12439     }
12440     theDI << "Statistic info:\n" << aView->StatisticInformation();
12441   }
12442   return 0;
12443 }
12444
12445 //=======================================================================
12446 //function : VXRotate
12447 //purpose  :
12448 //=======================================================================
12449 static Standard_Integer VXRotate (Draw_Interpretor& di,
12450                                    Standard_Integer argc,
12451                                    const char ** argv)
12452 {
12453   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12454   if (aContext.IsNull())
12455   {
12456     di << argv[0] << "ERROR : use 'vinit' command before \n";
12457     return 1;
12458   }
12459
12460   if (argc != 3)
12461   {
12462     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12463     return 1;
12464   }
12465
12466   TCollection_AsciiString aName (argv[1]);
12467   Standard_Real anAngle = Draw::Atof (argv[2]);
12468
12469   // find object
12470   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12471   Handle(AIS_InteractiveObject) anIObj;
12472   if (!aMap.Find2 (aName, anIObj))
12473   {
12474     di << "Use 'vdisplay' before\n";
12475     return 1;
12476   }
12477
12478   gp_Trsf aTransform;
12479   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12480   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12481
12482   aContext->SetLocation (anIObj, aTransform);
12483   aContext->UpdateCurrentViewer();
12484   return 0;
12485 }
12486
12487 //===============================================================================================
12488 //class   : ViewerTest_AISManipulator
12489 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12490 //===============================================================================================
12491 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12492
12493 class ViewerTest_AISManipulator : public AIS_Manipulator
12494 {
12495 public:
12496
12497   ViewerTest_AISManipulator() : AIS_Manipulator()
12498   {
12499     GetMapOfAISManipulators().Add (this);
12500   }
12501
12502   virtual ~ViewerTest_AISManipulator()
12503   {
12504     GetMapOfAISManipulators().Remove (this);
12505   }
12506
12507   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12508 };
12509
12510 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12511 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12512
12513 //===============================================================================================
12514 //function : VManipulator
12515 //purpose  :
12516 //===============================================================================================
12517 static int VManipulator (Draw_Interpretor& theDi,
12518                          Standard_Integer  theArgsNb,
12519                          const char**      theArgVec)
12520 {
12521   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12522   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12523   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12524   if (aCurrentView.IsNull()
12525    || aViewer.IsNull())
12526   {
12527     std::cerr << "No active viewer!\n";
12528     return 1;
12529   }
12530
12531   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12532   Standard_Integer anArgIter = 1;
12533   for (; anArgIter < theArgsNb; ++anArgIter)
12534   {
12535     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12536   }
12537
12538   ViewerTest_CmdParser aCmd;
12539   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12540   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12541   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12542   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12543   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12544   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12545   aCmd.AddOption ("detach",         "...       - detach manipulator");
12546
12547   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12548   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12549   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12550
12551   aCmd.AddOption ("move",   "... x y z - move object");
12552   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12553   aCmd.AddOption ("scale",  "... factor - scale object");
12554
12555   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12556   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12557   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12558   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12559   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12560   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12561   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12562   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12563   aCmd.AddOption ("size",              "... size - set size of manipulator");
12564   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12565
12566   aCmd.Parse (theArgsNb, theArgVec);
12567
12568   if (aCmd.HasOption ("help"))
12569   {
12570     theDi.PrintHelp (theArgVec[0]);
12571     return 0;
12572   }
12573
12574   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12575
12576   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12577
12578   if (aName.IsEmpty())
12579   {
12580     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12581     return 1;
12582   }
12583
12584   // ----------------------------------
12585   // detach existing manipulator object
12586   // ----------------------------------
12587
12588   if (aCmd.HasOption ("detach"))
12589   {
12590     if (!aMapAIS.IsBound2 (aName))
12591     {
12592       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12593       return 1;
12594     }
12595
12596     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12597     if (aManipulator.IsNull())
12598     {
12599       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12600       return 1;
12601     }
12602
12603     aManipulator->Detach();
12604     aMapAIS.UnBind2 (aName);
12605     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12606
12607     return 0;
12608   }
12609
12610   // -----------------------------------------------
12611   // find or create manipulator if it does not exist
12612   // -----------------------------------------------
12613
12614   Handle(AIS_Manipulator) aManipulator;
12615   if (!aMapAIS.IsBound2 (aName))
12616   {
12617     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12618
12619     aManipulator = new ViewerTest_AISManipulator();
12620     aManipulator->SetModeActivationOnDetection (true);
12621     aMapAIS.Bind (aManipulator, aName);
12622   }
12623   else
12624   {
12625     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12626     if (aManipulator.IsNull())
12627     {
12628       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12629       return 1;
12630     }
12631   }
12632
12633   // -----------------------------------------
12634   // change properties of manipulator instance
12635   // -----------------------------------------
12636
12637   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12638   {
12639     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12640   }
12641   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12642   {
12643     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12644   }
12645   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12646   {
12647     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12648   }
12649   if (aCmd.HasOption("followDragging", 1, Standard_True))
12650   {
12651     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12652   }
12653   if (aCmd.HasOption ("gap", 1, Standard_True))
12654   {
12655     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12656   }
12657   if (aCmd.HasOption ("part", 3, Standard_True))
12658   {
12659     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12660     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12661     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12662     if (aMode < 1 || aMode > 4)
12663     {
12664       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12665       return 1;
12666     }
12667
12668     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12669   }
12670   if (aCmd.HasOption("parts", 2, Standard_True))
12671   {
12672     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12673     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12674     if (aMode < 1 || aMode > 4)
12675     {
12676       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12677       return 1;
12678     }
12679
12680     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12681   }
12682   if (aCmd.HasOption ("pos", 3, Standard_True))
12683   {
12684     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12685     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12686     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12687
12688     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12689   }
12690   if (aCmd.HasOption ("size", 1, Standard_True))
12691   {
12692     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12693   }
12694   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12695   {
12696     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12697
12698     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12699     {
12700       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12701       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12702     }
12703   }
12704
12705   // ---------------------------------------------------
12706   // attach, detach or access manipulator from an object
12707   // ---------------------------------------------------
12708
12709   if (aCmd.HasOption ("attach"))
12710   {
12711     // Find an object and attach manipulator to it
12712     if (!aCmd.HasOption ("attach", 1, Standard_True))
12713     {
12714       return 1;
12715     }
12716
12717     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12718     Handle(AIS_InteractiveObject) anObject;
12719     if (!aMapAIS.Find2 (anObjName, anObject))
12720     {
12721       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12722       return 1;
12723     }
12724
12725     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12726     {
12727       if (anIt.Value()->IsAttached()
12728        && anIt.Value()->Object() == anObject)
12729       {
12730         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12731         return 1;
12732       }
12733     }
12734
12735     AIS_Manipulator::OptionsForAttach anOptions;
12736     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12737     {
12738       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12739     }
12740     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12741     {
12742       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12743     }
12744     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12745     {
12746       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12747     }
12748
12749     aManipulator->Attach (anObject, anOptions);
12750
12751     // Check view option
12752     if (aCmd.HasOption ("view"))
12753     {
12754       if (!aCmd.HasOption ("view", 1, Standard_True))
12755       {
12756         return 1;
12757       }
12758       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12759       Handle(V3d_View) aView;
12760       if (aViewString.IsEqual ("active"))
12761       {
12762         aView = ViewerTest::CurrentView();
12763       }
12764       else // Check view name
12765       {
12766         ViewerTest_Names aViewNames (aViewString);
12767         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12768         {
12769           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12770           return 1;
12771         }
12772         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12773         if (aView.IsNull())
12774         {
12775           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12776           return 1;
12777         }
12778       }
12779       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12780         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12781       {
12782         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12783       }
12784       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12785     }
12786   }
12787
12788   // --------------------------------------
12789   // apply transformation using manipulator
12790   // --------------------------------------
12791
12792   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12793   {
12794     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12795   }
12796   if (aCmd.HasOption ("transform", 2, Standard_True))
12797   {
12798     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12799   }
12800   if (aCmd.HasOption ("stopTransform"))
12801   {
12802     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12803
12804     aManipulator->StopTransform (toApply);
12805   }
12806
12807   gp_Trsf aT;
12808   if (aCmd.HasOption ("move", 3, Standard_True))
12809   {
12810     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12811   }
12812   if (aCmd.HasOption ("rotate", 7, Standard_True))
12813   {
12814     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12815   }
12816   if (aCmd.HasOption ("scale", 1))
12817   {
12818     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12819   }
12820
12821   if (aT.Form() != gp_Identity)
12822   {
12823     aManipulator->Transform (aT);
12824   }
12825
12826   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12827
12828   return 0;
12829 }
12830
12831 //===============================================================================================
12832 //function : VSelectionProperties
12833 //purpose  :
12834 //===============================================================================================
12835 static int VSelectionProperties (Draw_Interpretor& theDi,
12836                                  Standard_Integer  theArgsNb,
12837                                  const char**      theArgVec)
12838 {
12839   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12840   if (aCtx.IsNull())
12841   {
12842     std::cerr << "No active viewer!\n";
12843     return 1;
12844   }
12845
12846   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12847   {
12848     // handle obsolete alias
12849     bool toEnable = true;
12850     if (theArgsNb < 2)
12851     {
12852       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12853       return 0;
12854     }
12855     else if (theArgsNb != 2
12856          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12857     {
12858       std::cout << "Syntax error: wrong number of parameters.";
12859       return 1;
12860     }
12861     if (toEnable != aCtx->ToHilightSelected())
12862     {
12863       aCtx->ClearDetected();
12864       aCtx->SetToHilightSelected (toEnable);
12865     }
12866     return 0;
12867   }
12868
12869   Standard_Boolean toPrint  = theArgsNb == 1;
12870   Standard_Boolean toRedraw = Standard_False;
12871   Standard_Integer anArgIter = 1;
12872   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12873   if (anArgIter < theArgsNb)
12874   {
12875     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12876     anArgFirst.LowerCase();
12877     ++anArgIter;
12878     if (anArgFirst == "dynhighlight"
12879      || anArgFirst == "dynhilight"
12880      || anArgFirst == "dynamichighlight"
12881      || anArgFirst == "dynamichilight")
12882     {
12883       aType = Prs3d_TypeOfHighlight_Dynamic;
12884     }
12885     else if (anArgFirst == "localdynhighlight"
12886           || anArgFirst == "localdynhilight"
12887           || anArgFirst == "localdynamichighlight"
12888           || anArgFirst == "localdynamichilight")
12889     {
12890       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12891     }
12892     else if (anArgFirst == "selhighlight"
12893           || anArgFirst == "selhilight"
12894           || anArgFirst == "selectedhighlight"
12895           || anArgFirst == "selectedhilight")
12896     {
12897       aType = Prs3d_TypeOfHighlight_Selected;
12898     }
12899     else if (anArgFirst == "localselhighlight"
12900           || anArgFirst == "localselhilight"
12901           || anArgFirst == "localselectedhighlight"
12902           || anArgFirst == "localselectedhilight")
12903     {
12904       aType = Prs3d_TypeOfHighlight_LocalSelected;
12905     }
12906     else
12907     {
12908       --anArgIter;
12909     }
12910   }
12911   for (; anArgIter < theArgsNb; ++anArgIter)
12912   {
12913     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12914     anArg.LowerCase();
12915     if (anArg == "-help")
12916     {
12917       theDi.PrintHelp (theArgVec[0]);
12918       return 0;
12919     }
12920     else if (anArg == "-print")
12921     {
12922       toPrint = Standard_True;
12923     }
12924     else if (anArg == "-autoactivate")
12925     {
12926       Standard_Boolean toEnable = Standard_True;
12927       if (anArgIter + 1 < theArgsNb
12928        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12929       {
12930         ++anArgIter;
12931       }
12932       aCtx->SetAutoActivateSelection (toEnable);
12933     }
12934     else if (anArg == "-automatichighlight"
12935           || anArg == "-automatichilight"
12936           || anArg == "-autohighlight"
12937           || anArg == "-autohilight")
12938     {
12939       Standard_Boolean toEnable = Standard_True;
12940       if (anArgIter + 1 < theArgsNb
12941        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12942       {
12943         ++anArgIter;
12944       }
12945       aCtx->ClearSelected (false);
12946       aCtx->ClearDetected();
12947       aCtx->SetAutomaticHilight (toEnable);
12948       toRedraw = true;
12949     }
12950     else if (anArg == "-highlightselected"
12951           || anArg == "-hilightselected")
12952     {
12953       Standard_Boolean toEnable = Standard_True;
12954       if (anArgIter + 1 < theArgsNb
12955        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12956       {
12957         ++anArgIter;
12958       }
12959       aCtx->ClearDetected();
12960       aCtx->SetToHilightSelected (toEnable);
12961       toRedraw = true;
12962     }
12963     else if (anArg == "-pickstrategy"
12964           || anArg == "-pickingstrategy")
12965     {
12966       if (++anArgIter >= theArgsNb)
12967       {
12968         std::cout << "Syntax error: type of highlighting is undefined\n";
12969         return 1;
12970       }
12971
12972       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12973       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12974       aVal.LowerCase();
12975       if (aVal == "first"
12976        || aVal == "firstaccepted"
12977        || aVal == "firstacceptable")
12978       {
12979         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12980       }
12981       else if (aVal == "topmost"
12982             || aVal == "onlyTopmost")
12983       {
12984         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12985       }
12986       else
12987       {
12988         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12989         return 1;
12990       }
12991
12992       aCtx->SetPickingStrategy (aStrategy);
12993     }
12994     else if (anArg == "-pixtol"
12995           && anArgIter + 1 < theArgsNb)
12996     {
12997       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12998     }
12999     else if ((anArg == "-mode"
13000            || anArg == "-dispmode")
13001           && anArgIter + 1 < theArgsNb)
13002     {
13003       if (aType == Prs3d_TypeOfHighlight_None)
13004       {
13005         std::cout << "Syntax error: type of highlighting is undefined\n";
13006         return 1;
13007       }
13008
13009       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
13010       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13011       aStyle->SetDisplayMode (aDispMode);
13012       toRedraw = Standard_True;
13013     }
13014     else if (anArg == "-layer"
13015           && anArgIter + 1 < theArgsNb)
13016     {
13017       if (aType == Prs3d_TypeOfHighlight_None)
13018       {
13019         std::cout << "Syntax error: type of highlighting is undefined\n";
13020         return 1;
13021       }
13022
13023       ++anArgIter;
13024       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
13025       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
13026       {
13027         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
13028         return 1;
13029       }
13030
13031       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13032       aStyle->SetZLayer (aNewLayer);
13033       toRedraw = Standard_True;
13034     }
13035     else if (anArg == "-hicolor"
13036           || anArg == "-selcolor"
13037           || anArg == "-color")
13038     {
13039       if (anArg.StartsWith ("-hi"))
13040       {
13041         aType = Prs3d_TypeOfHighlight_Dynamic;
13042       }
13043       else if (anArg.StartsWith ("-sel"))
13044       {
13045         aType = Prs3d_TypeOfHighlight_Selected;
13046       }
13047       else if (aType == Prs3d_TypeOfHighlight_None)
13048       {
13049         std::cout << "Syntax error: type of highlighting is undefined\n";
13050         return 1;
13051       }
13052
13053       Quantity_Color aColor;
13054       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
13055                                                            theArgVec + anArgIter + 1,
13056                                                            aColor);
13057       if (aNbParsed == 0)
13058       {
13059         std::cout << "Syntax error: need more arguments.\n";
13060         return 1;
13061       }
13062       anArgIter += aNbParsed;
13063
13064       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13065       aStyle->SetColor (aColor);
13066       toRedraw = Standard_True;
13067     }
13068     else if ((anArg == "-transp"
13069            || anArg == "-transparency"
13070            || anArg == "-hitransp"
13071            || anArg == "-seltransp"
13072            || anArg == "-hitransplocal"
13073            || anArg == "-seltransplocal")
13074           && anArgIter + 1 < theArgsNb)
13075     {
13076       if (anArg.StartsWith ("-hi"))
13077       {
13078         aType = Prs3d_TypeOfHighlight_Dynamic;
13079       }
13080       else if (anArg.StartsWith ("-sel"))
13081       {
13082         aType = Prs3d_TypeOfHighlight_Selected;
13083       }
13084       else if (aType == Prs3d_TypeOfHighlight_None)
13085       {
13086         std::cout << "Syntax error: type of highlighting is undefined\n";
13087         return 1;
13088       }
13089
13090       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
13091       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13092       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
13093       toRedraw = Standard_True;
13094     }
13095     else if ((anArg == "-mat"
13096            || anArg == "-material")
13097           && anArgIter + 1 < theArgsNb)
13098     {
13099       if (aType == Prs3d_TypeOfHighlight_None)
13100       {
13101         std::cout << "Syntax error: type of highlighting is undefined\n";
13102         return 1;
13103       }
13104
13105       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
13106       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
13107       if (aMatName != Graphic3d_NOM_DEFAULT)
13108       {
13109         ++anArgIter;
13110         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
13111         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
13112         Graphic3d_MaterialAspect aMat (aMatName);
13113         aMat.SetColor (aStyle->Color());
13114         aMat.SetTransparency (aStyle->Transparency());
13115         anAspect->SetFrontMaterial (aMat);
13116         anAspect->SetInteriorColor (aStyle->Color());
13117         aStyle->SetBasicFillAreaAspect (anAspect);
13118       }
13119       else
13120       {
13121         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
13122       }
13123       toRedraw = Standard_True;
13124     }
13125     else
13126     {
13127       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
13128     }
13129   }
13130
13131   if (toPrint)
13132   {
13133     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
13134     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
13135     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
13136     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
13137     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
13138     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
13139     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
13140     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
13141     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
13142     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
13143     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
13144     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
13145     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
13146     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
13147   }
13148
13149   if (aCtx->NbSelected() != 0 && toRedraw)
13150   {
13151     aCtx->HilightSelected (Standard_True);
13152   }
13153
13154   return 0;
13155 }
13156
13157 //===============================================================================================
13158 //function : VDumpSelectionImage
13159 //purpose  :
13160 //===============================================================================================
13161 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
13162                                 Standard_Integer  theArgsNb,
13163                                 const char**      theArgVec)
13164 {
13165   if (theArgsNb < 2)
13166   {
13167     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
13168     return 1;
13169   }
13170
13171   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13172   if (aContext.IsNull())
13173   {
13174     std::cout << "Error: no active view.\n";
13175     return 1;
13176   }
13177
13178   TCollection_AsciiString aFile;
13179   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13180   Image_Format anImgFormat = Image_Format_BGR;
13181   Standard_Integer aPickedIndex = 1;
13182   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
13183   {
13184     TCollection_AsciiString aParam (theArgVec[anArgIter]);
13185     aParam.LowerCase();
13186     if (aParam == "-type")
13187     {
13188       if (++anArgIter >= theArgsNb)
13189       {
13190         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
13191         return 1;
13192       }
13193
13194       TCollection_AsciiString aValue (theArgVec[anArgIter]);
13195       aValue.LowerCase();
13196       if (aValue == "depth"
13197        || aValue == "normdepth"
13198        || aValue == "normalizeddepth")
13199       {
13200         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
13201         anImgFormat = Image_Format_GrayF;
13202       }
13203       if (aValue == "depthinverted"
13204        || aValue == "normdepthinverted"
13205        || aValue == "normalizeddepthinverted"
13206        || aValue == "inverted")
13207       {
13208         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13209         anImgFormat = Image_Format_GrayF;
13210       }
13211       else if (aValue == "unnormdepth"
13212             || aValue == "unnormalizeddepth")
13213       {
13214         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13215         anImgFormat = Image_Format_GrayF;
13216       }
13217       else if (aValue == "objectcolor"
13218             || aValue == "object"
13219             || aValue == "color")
13220       {
13221         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13222       }
13223       else if (aValue == "entitycolor"
13224             || aValue == "entity")
13225       {
13226         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13227       }
13228       else if (aValue == "ownercolor"
13229             || aValue == "owner")
13230       {
13231         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13232       }
13233       else if (aValue == "selectionmodecolor"
13234             || aValue == "selectionmode"
13235             || aValue == "selmodecolor"
13236             || aValue == "selmode")
13237       {
13238         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13239       }
13240     }
13241     else if (aParam == "-picked"
13242           || aParam == "-pickeddepth"
13243           || aParam == "-pickedindex")
13244     {
13245       if (++anArgIter >= theArgsNb)
13246       {
13247         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13248         return 1;
13249       }
13250
13251       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13252     }
13253     else if (aFile.IsEmpty())
13254     {
13255       aFile = theArgVec[anArgIter];
13256     }
13257     else
13258     {
13259       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13260       return 1;
13261     }
13262   }
13263   if (aFile.IsEmpty())
13264   {
13265     std::cout << "Syntax error: image file name is missing.\n";
13266     return 1;
13267   }
13268
13269   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13270   Standard_Integer aWidth = 0, aHeight = 0;
13271   aView->Window()->Size (aWidth, aHeight);
13272
13273   Image_AlienPixMap aPixMap;
13274   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13275   {
13276     std::cout << "Error: can't allocate image.\n";
13277     return 1;
13278   }
13279   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13280   {
13281     std::cout << "Error: can't generate selection image.\n";
13282     return 1;
13283   }
13284   if (!aPixMap.Save (aFile))
13285   {
13286     std::cout << "Error: can't save selection image.\n";
13287     return 0;
13288   }
13289   return 0;
13290 }
13291
13292 //===============================================================================================
13293 //function : VViewCube
13294 //purpose  :
13295 //===============================================================================================
13296 static int VViewCube (Draw_Interpretor& ,
13297                       Standard_Integer  theNbArgs,
13298                       const char**      theArgVec)
13299 {
13300   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
13301   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13302   if (aContext.IsNull() || aView.IsNull())
13303   {
13304     std::cout << "Error: no active view.\n";
13305     return 1;
13306   }
13307   else if (theNbArgs < 2)
13308   {
13309     std::cout << "Syntax error: wrong number arguments\n";
13310     return 1;
13311   }
13312
13313   Handle(AIS_ViewCube) aViewCube;
13314   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
13315   Quantity_Color aColorRgb;
13316   TCollection_AsciiString aName;
13317   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
13318   {
13319     TCollection_AsciiString anArg (theArgVec[anArgIter]);
13320     anArg.LowerCase();
13321     if (anUpdateTool.parseRedrawMode (anArg))
13322     {
13323       //
13324     }
13325     else if (aViewCube.IsNull())
13326     {
13327       aName = theArgVec[anArgIter];
13328       if (aName.StartsWith ("-"))
13329       {
13330         std::cout << "Syntax error: object name should be specified.\n";
13331         return 1;
13332       }
13333       Handle(AIS_InteractiveObject) aPrs;
13334       GetMapOfAIS().Find2 (aName, aPrs);
13335       aViewCube = Handle(AIS_ViewCube)::DownCast (aPrs);
13336       if (aViewCube.IsNull())
13337       {
13338         aViewCube = new AIS_ViewCube();
13339         aViewCube->SetBoxColor (Quantity_NOC_GRAY50);
13340         aViewCube->SetViewAnimation (ViewerTest::CurrentEventManager()->ViewAnimation());
13341         aViewCube->SetFixedAnimationLoop (false);
13342       }
13343     }
13344     else if (anArg == "-reset")
13345     {
13346       aViewCube->ResetStyles();
13347     }
13348     else if (anArg == "-color"
13349           || anArg == "-boxcolor"
13350           || anArg == "-boxsidecolor"
13351           || anArg == "-sidecolor"
13352           || anArg == "-boxedgecolor"
13353           || anArg == "-edgecolor"
13354           || anArg == "-boxcornercolor"
13355           || anArg == "-cornercolor"
13356           || anArg == "-innercolor"
13357           || anArg == "-textcolor")
13358     {
13359       Standard_Integer aNbParsed = ViewerTest::ParseColor (theNbArgs - anArgIter - 1,
13360                                                            theArgVec + anArgIter + 1,
13361                                                            aColorRgb);
13362       if (aNbParsed == 0)
13363       {
13364         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
13365         return 1;
13366       }
13367       anArgIter += aNbParsed;
13368       if (anArg == "-boxcolor")
13369       {
13370         aViewCube->SetBoxColor (aColorRgb);
13371       }
13372       else if (anArg == "-boxsidecolor"
13373             || anArg == "-sidecolor")
13374       {
13375         aViewCube->BoxSideStyle()->SetColor (aColorRgb);
13376         aViewCube->SynchronizeAspects();
13377       }
13378       else if (anArg == "-boxedgecolor"
13379             || anArg == "-edgecolor")
13380       {
13381         aViewCube->BoxEdgeStyle()->SetColor (aColorRgb);
13382         aViewCube->SynchronizeAspects();
13383       }
13384       else if (anArg == "-boxcornercolor"
13385             || anArg == "-cornercolor")
13386       {
13387         aViewCube->BoxCornerStyle()->SetColor (aColorRgb);
13388         aViewCube->SynchronizeAspects();
13389       }
13390       else if (anArg == "-innercolor")
13391       {
13392         aViewCube->SetInnerColor (aColorRgb);
13393       }
13394       else if (anArg == "-textcolor")
13395       {
13396         aViewCube->SetTextColor (aColorRgb);
13397       }
13398       else
13399       {
13400         aViewCube->SetColor (aColorRgb);
13401       }
13402     }
13403     else if (anArgIter + 1 < theNbArgs
13404           && (anArg == "-transparency"
13405            || anArg == "-boxtransparency"))
13406     {
13407       const Standard_Real aValue = Draw::Atof (theArgVec[++anArgIter]);
13408       if (aValue < 0.0 || aValue > 1.0)
13409       {
13410         std::cout << "Syntax error: invalid transparency value " << theArgVec[anArgIter] << "\n";
13411         return 1;
13412       }
13413
13414       if (anArg == "-boxtransparency")
13415       {
13416         aViewCube->SetBoxTransparency (aValue);
13417       }
13418       else
13419       {
13420         aViewCube->SetTransparency (aValue);
13421       }
13422     }
13423     else if (anArg == "-axes"
13424           || anArg == "-edges"
13425           || anArg == "-vertices"
13426           || anArg == "-vertexes"
13427           || anArg == "-fixedanimation")
13428     {
13429       bool toShow = true;
13430       if (anArgIter + 1 < theNbArgs
13431        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toShow))
13432       {
13433         ++anArgIter;
13434       }
13435       if (anArg == "-fixedanimation")
13436       {
13437         aViewCube->SetFixedAnimationLoop (toShow);
13438       }
13439       else if (anArg == "-axes")
13440       {
13441         aViewCube->SetDrawAxes (toShow);
13442       }
13443       else if (anArg == "-edges")
13444       {
13445         aViewCube->SetDrawEdges (toShow);
13446       }
13447       else
13448       {
13449         aViewCube->SetDrawVertices (toShow);
13450       }
13451     }
13452     else if (anArg == "-yup"
13453           || anArg == "-zup")
13454     {
13455       bool isOn = true;
13456       if (anArgIter + 1 < theNbArgs
13457        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isOn))
13458       {
13459         ++anArgIter;
13460       }
13461       if (anArg == "-yup")
13462       {
13463         aViewCube->SetYup (isOn);
13464       }
13465       else
13466       {
13467         aViewCube->SetYup (!isOn);
13468       }
13469     }
13470     else if (anArgIter + 1 < theNbArgs
13471           && anArg == "-font")
13472     {
13473       aViewCube->SetFont (theArgVec[++anArgIter]);
13474     }
13475     else if (anArgIter + 1 < theNbArgs
13476           && anArg == "-fontheight")
13477     {
13478       aViewCube->SetFontHeight (Draw::Atof (theArgVec[++anArgIter]));
13479     }
13480     else if (anArgIter + 1 < theNbArgs
13481           && (anArg == "-size"
13482            || anArg == "-boxsize"))
13483     {
13484       aViewCube->SetSize (Draw::Atof (theArgVec[++anArgIter]),
13485                           anArg != "-boxsize");
13486     }
13487     else if (anArgIter + 1 < theNbArgs
13488           && (anArg == "-boxfacet"
13489            || anArg == "-boxfacetextension"
13490            || anArg == "-facetextension"
13491            || anArg == "-extension"))
13492     {
13493       aViewCube->SetBoxFacetExtension (Draw::Atof (theArgVec[++anArgIter]));
13494     }
13495     else if (anArgIter + 1 < theNbArgs
13496           && (anArg == "-boxedgegap"
13497            || anArg == "-edgegap"))
13498     {
13499       aViewCube->SetBoxEdgeGap (Draw::Atof (theArgVec[++anArgIter]));
13500     }
13501     else if (anArgIter + 1 < theNbArgs
13502           && (anArg == "-boxedgeminsize"
13503            || anArg == "-edgeminsize"))
13504     {
13505       aViewCube->SetBoxEdgeMinSize (Draw::Atof (theArgVec[++anArgIter]));
13506     }
13507     else if (anArgIter + 1 < theNbArgs
13508           && (anArg == "-boxcornerminsize"
13509            || anArg == "-cornerminsize"))
13510     {
13511       aViewCube->SetBoxCornerMinSize (Draw::Atof (theArgVec[++anArgIter]));
13512     }
13513     else if (anArgIter + 1 < theNbArgs
13514           && anArg == "-axespadding")
13515     {
13516       aViewCube->SetAxesPadding (Draw::Atof (theArgVec[++anArgIter]));
13517     }
13518     else if (anArgIter + 1 < theNbArgs
13519           && anArg == "-roundradius")
13520     {
13521       aViewCube->SetRoundRadius (Draw::Atof (theArgVec[++anArgIter]));
13522     }
13523     else if (anArgIter + 1 < theNbArgs
13524           && anArg == "-duration")
13525     {
13526       aViewCube->SetDuration (Draw::Atof (theArgVec[++anArgIter]));
13527     }
13528     else
13529     {
13530       std::cout << "Syntax error: unknown argument '" << anArg << "'\n";
13531       return 1;
13532     }
13533   }
13534   if (aViewCube.IsNull())
13535   {
13536     std::cout << "Syntax error: wrong number of arguments\n";
13537     return 1;
13538   }
13539
13540   ViewerTest::Display (aName, aViewCube, false);
13541   return 0;
13542 }
13543
13544 //=======================================================================
13545 //function : ViewerCommands
13546 //purpose  :
13547 //=======================================================================
13548
13549 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13550 {
13551
13552   const char *group = "ZeViewer";
13553   theCommands.Add("vinit",
13554           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13555     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13556   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13557     "\n\t\t:     [-display displayName]"
13558   #endif
13559     "\n\t\t: Creates new View window with specified name viewName."
13560     "\n\t\t: By default the new view is created in the viewer and in"
13561     "\n\t\t: graphic driver shared with active view."
13562     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13563     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13564     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13565 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13566     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13567     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13568 #endif
13569     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13570     "\n\t\t:  -width, -height width and heigth of window respectively."
13571     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13572     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13573     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13574     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13575     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13576     __FILE__,VInit,group);
13577   theCommands.Add("vclose" ,
13578     "[view_id [keep_context=0|1]]\n"
13579     "or vclose ALL - to remove all created views\n"
13580     " - removes view(viewer window) defined by its view_id.\n"
13581     " - keep_context: by default 0; if 1 and the last view is deleted"
13582     " the current context is not removed.",
13583     __FILE__,VClose,group);
13584   theCommands.Add("vactivate" ,
13585     "vactivate view_id [-noUpdate]"
13586     " - activates view(viewer window) defined by its view_id",
13587     __FILE__,VActivate,group);
13588   theCommands.Add("vviewlist",
13589     "vviewlist [format={tree, long}]"
13590     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13591     " - format: format of result output, if tree the output is a tree view;"
13592     "otherwise it's a list of full view names. By default format = tree",
13593     __FILE__,VViewList,group);
13594   theCommands.Add("vhelp" ,
13595     "vhelp            : display help on the viewer commands",
13596     __FILE__,VHelp,group);
13597   theCommands.Add("vviewproj",
13598           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13599     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13600     "\n\t\t: Setup view direction"
13601     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13602     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13603     "\n\t\t:             for example '+Z' will show front of the model,"
13604     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13605     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13606     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13607     __FILE__,VViewProj,group);
13608   theCommands.Add("vtop" ,
13609     "vtop or <T>      : Top view. Orientation +X+Y" ,
13610     __FILE__,VViewProj,group);
13611   theCommands.Add("vbottom" ,
13612     "vbottom          : Bottom view. Orientation +X-Y" ,
13613     __FILE__,VViewProj,group);
13614   theCommands.Add("vleft" ,
13615     "vleft            : Left view. Orientation -Y+Z" ,
13616     __FILE__,VViewProj,group);
13617   theCommands.Add("vright" ,
13618     "vright           : Right view. Orientation +Y+Z" ,
13619     __FILE__,VViewProj,group);
13620   theCommands.Add("vaxo" ,
13621     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13622     __FILE__,VViewProj,group);
13623   theCommands.Add("vfront" ,
13624     "vfront           : Front view. Orientation +X+Z" ,
13625     __FILE__,VViewProj,group);
13626   theCommands.Add("vback" ,
13627     "vback            : Back view. Orientation -X+Z" ,
13628     __FILE__,VViewProj,group);
13629   theCommands.Add("vpick" ,
13630     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13631     VPick,group);
13632   theCommands.Add("vfit",
13633     "vfit or <F> [-selected] [-noupdate]"
13634     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13635     __FILE__,VFit,group);
13636   theCommands.Add ("vfitarea",
13637     "vfitarea x1 y1 x2 y2"
13638     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13639     "\n\t\t: Fit view to show area located between two points"
13640     "\n\t\t: given in world 2D or 3D corrdinates.",
13641     __FILE__, VFitArea, group);
13642   theCommands.Add ("vzfit", "vzfit [scale]\n"
13643     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13644     "   \"scale\" - specifies factor to scale computed z range.\n",
13645     __FILE__, VZFit, group);
13646   theCommands.Add("vrepaint",
13647             "vrepaint [-immediate] [-continuous FPS]"
13648     "\n\t\t: force redraw of active View"
13649     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13650     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13651     "\n\t\t:                0 means no continuous rendering,"
13652     "\n\t\t:               -1 means non-stop redraws,"
13653     "\n\t\t:               >0 specifies target framerate,",
13654     __FILE__,VRepaint,group);
13655   theCommands.Add("vclear",
13656     "vclear          : vclear"
13657     "\n\t\t: remove all the object from the viewer",
13658     __FILE__,VClear,group);
13659   theCommands.Add (
13660     "vbackground",
13661     "Changes background or some background settings.\n"
13662     "\n"
13663     "Usage:\n"
13664     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13665     "  vbackground -imageMode FillType\n"
13666     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13667     "  vbackground -gradientMode FillMethod\n"
13668     "  vbackground -cubemap CubemapFile1 [CubeMapFiles2-5] [-order TilesIndexes1-6] [-invertedz]\n"
13669     "  vbackground -color Color\n"
13670     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13671     "  vbackground -default -color Color\n"
13672     "  vbackground -help\n"
13673     "\n"
13674     "Options:\n"
13675     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13676     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13677     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13678     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13679     "  -cubemap      (-cmap, -cm):                         sets environmet cubemap as background\n"
13680     "  -invertedz    (-invz, -iz):                         sets inversion of Z axis for background cubemap rendering\n"
13681     "  -order        (-o):                                 defines order of tiles in one image cubemap\n"
13682     "                                                      (has no effect in case of multi image cubemaps)\n"
13683     "  -color        (-col):                               sets background color\n"
13684     "  -default      (-def):                               sets background default gradient or color\n"
13685     "  -help         (-h):                                 outputs short help message\n"
13686     "\n"
13687     "Arguments:\n"
13688     "  Color:        Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13689     "                                  or reals within the range [0.0, 1.0]\n"
13690     "                ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13691     "                #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13692     "  FillMethod:   one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13693     "CORNER4\n"
13694     "  FillType:     one of CENTERED, TILED, STRETCH, NONE\n"
13695     "  ImageFile:    a name of the file with the image used as a background\n"
13696     "  CubemapFilei: a name of the file with one image packed cubemap or names of separate files with every cubemap side\n"
13697     "  TileIndexi:   a cubemap side index in range [0, 5] for i tile of one image packed cubemap\n",
13698     __FILE__,
13699     vbackground,
13700     group);
13701   theCommands.Add ("vsetbg",
13702                    "Loads image as background."
13703                    "\n\t\t: vsetbg ImageFile [FillType]"
13704                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13705                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13706                    __FILE__,
13707                    vbackground,
13708                    group);
13709   theCommands.Add ("vsetbgmode",
13710                    "Changes background image fill type."
13711                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13712                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13713                    __FILE__,
13714                    vbackground,
13715                    group);
13716   theCommands.Add ("vsetgradientbg",
13717                    "Mounts gradient background."
13718                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13719                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13720                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13721                    __FILE__,
13722                    vbackground,
13723                    group);
13724   theCommands.Add ("vsetgrbgmode",
13725                    "Changes gradient background fill method."
13726                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13727                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13728                    __FILE__,
13729                    vbackground,
13730                    group);
13731   theCommands.Add ("vsetcolorbg",
13732                    "Sets background color."
13733                    "\n\t\t: vsetcolorbg [-color] Color."
13734                    "\n\t\t: Alias for 'vbackground -color Color'.",
13735                    __FILE__,
13736                    vbackground,
13737                    group);
13738   theCommands.Add ("vsetdefaultbg",
13739                    "Sets default viewer background fill color (flat/gradient)."
13740                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13741                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13742                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13743                    "\n\t\t: vsetdefaultbg [-color] Color"
13744                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13745                    __FILE__,
13746                    vbackground,
13747                    group);
13748   theCommands.Add("vscale",
13749     "vscale          : vscale X Y Z",
13750     __FILE__,VScale,group);
13751   theCommands.Add("vzbufftrihedron",
13752             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13753     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13754     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13755     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13756     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13757     "\n\t\t: Displays a trihedron",
13758     __FILE__,VZBuffTrihedron,group);
13759   theCommands.Add("vrotate",
13760     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13761     "\n                : Option -mouseStart starts rotation according to the mouse position"
13762     "\n                : Option -mouseMove continues rotation with angle computed"
13763     "\n                : from last and new mouse position."
13764     "\n                : vrotate AX AY AZ [X Y Z]",
13765     __FILE__,VRotate,group);
13766   theCommands.Add("vzoom",
13767     "vzoom           : vzoom coef",
13768     __FILE__,VZoom,group);
13769   theCommands.Add("vpan",
13770     "vpan            : vpan dx dy",
13771     __FILE__,VPan,group);
13772   theCommands.Add("vcolorscale",
13773     "vcolorscale name [-noupdate|-update] [-demo]"
13774     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13775     "\n\t\t:       [-font HeightFont=20]"
13776     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13777     "\n\t\t:       [-smoothTransition {on|off}=off]"
13778     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13779     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13780     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13781     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13782     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13783     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13784     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13785     "\n\t\t:       [-xy Left=0 Bottom=0]"
13786     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13787     "\n\t\t:  -colors   - set colors for all intervals"
13788     "\n\t\t:  -color    - set color for specific interval"
13789     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13790     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13791     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13792     "\n\t\t:              at center means the center value within current interval"
13793     "\n\t\t:  -labels   - set labels for all intervals"
13794     "\n\t\t:  -freeLabels - same as -labels but does not require"
13795     "\n\t\t:              matching the number of intervals"
13796     "\n\t\t:  -label    - set label for specific interval"
13797     "\n\t\t:  -title    - set title"
13798     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13799     "\n\t\t:  -smoothTransition - swap colorscale direction"
13800     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13801     __FILE__, VColorScale, group);
13802   theCommands.Add("vgraduatedtrihedron",
13803     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13804     "\t[-namefont Name] [-valuesfont Name]\n"
13805     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13806     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13807     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13808     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13809     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13810     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13811     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13812     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13813     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13814     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13815     " - Displays or erases graduated trihedron"
13816     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13817     " - namefont - font of axes names. Default: Arial\n"
13818     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13819     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13820     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13821     " - valuesfont - font of axes values. Default: Arial\n"
13822     " - xcolor, ycolor, zcolor - color of axis and values\n"
13823     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13824     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13825     __FILE__,VGraduatedTrihedron,group);
13826   theCommands.Add("vtile" ,
13827             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13828     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13829     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13830     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13831     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13832     "\n\t\t:  -upperLeft tile offset as upper left corner",
13833     __FILE__, VTile, group);
13834   theCommands.Add("vzlayer",
13835               "vzlayer [layerId]"
13836       "\n\t\t:         [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]"
13837       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13838       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13839       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]"
13840       "\n\t\t: ZLayer list management:"
13841       "\n\t\t:   -add      add new z layer to viewer and print its id"
13842       "\n\t\t:   -insertBefore add new z layer and insert it before existing one"
13843       "\n\t\t:   -insertAfter  add new z layer and insert it after  existing one"
13844       "\n\t\t:   -delete   delete z layer"
13845       "\n\t\t:   -get      print sequence of z layers"
13846       "\n\t\t:   -settings print status of z layer settings"
13847       "\n\t\t:   -disable  disables given setting"
13848       "\n\t\t:   -enable   enables  given setting",
13849     __FILE__,VZLayer,group);
13850   theCommands.Add("vlayerline",
13851     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
13852     __FILE__,VLayerLine,group);
13853   theCommands.Add("vgrid",
13854               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
13855       "\n\t\t:       [-step X Y] [-size DX DY]"
13856       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
13857     __FILE__, VGrid, group);
13858   theCommands.Add ("vpriviledgedplane",
13859     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
13860     "\n\t\t:   Ox, Oy, Oz - plane origin"
13861     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
13862     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
13863     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
13864     __FILE__, VPriviledgedPlane, group);
13865   theCommands.Add ("vconvert",
13866     "vconvert v [Mode={window|view}]"
13867     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
13868     "\n\t\t: vconvert x y z [Mode={window|grid}]"
13869     "\n\t\t:   window - convert to window coordinates, pixels"
13870     "\n\t\t:   view   - convert to view projection plane"
13871     "\n\t\t:   grid   - convert to model coordinates, given on grid"
13872     "\n\t\t:   ray    - convert projection ray to model coordiantes"
13873     "\n\t\t: - vconvert v window : convert view to window;"
13874     "\n\t\t: - vconvert v view   : convert window to view;"
13875     "\n\t\t: - vconvert x y window : convert view to window;"
13876     "\n\t\t: - vconvert x y view : convert window to view;"
13877     "\n\t\t: - vconvert x y : convert window to model;"
13878     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
13879     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
13880     "\n\t\t: - vconvert x y z window : convert model to window;"
13881     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
13882     "\n\t\t: Converts the given coordinates to window/view/model space.",
13883     __FILE__, VConvert, group);
13884   theCommands.Add ("vfps",
13885     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
13886     __FILE__, VFps, group);
13887   theCommands.Add ("vgldebug",
13888             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
13889     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
13890     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
13891     "\n\t\t: Debug context can be requested only on Windows"
13892     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
13893     "\n\t\t:  -sync     - request synchronized debug GL context"
13894     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
13895     "\n\t\t:              which are suppressed by default,"
13896     "\n\t\t:  -glslCode - log GLSL program source code,"
13897     "\n\t\t:              which are suppressed by default,"
13898     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
13899     "\n\t\t:              which are suppressed by default",
13900     __FILE__, VGlDebug, group);
13901   theCommands.Add ("vvbo",
13902     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
13903     __FILE__, VVbo, group);
13904   theCommands.Add ("vstereo",
13905             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
13906     "\n\t\t:         [-anaglyph Filter]"
13907     "\n\t\t: Control stereo output mode. Available modes for -mode:"
13908     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
13909     "\n\t\t:                     requires driver support."
13910     "\n\t\t:                     Should be called BEFORE vinit!"
13911     "\n\t\t:  anaglyph         - Anaglyph glasses"
13912     "\n\t\t:  rowInterlaced    - row-interlaced display"
13913     "\n\t\t:  columnInterlaced - column-interlaced display"
13914     "\n\t\t:  chessBoard       - chess-board output"
13915     "\n\t\t:  sideBySide       - horizontal pair"
13916     "\n\t\t:  overUnder        - vertical   pair"
13917     "\n\t\t: Available Anaglyph filters for -anaglyph:"
13918     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
13919     "\n\t\t:  greenMagentaSimple",
13920     __FILE__, VStereo, group);
13921   theCommands.Add ("vcaps",
13922             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
13923     "\n\t\t:       [-compatibleProfile {0|1}]"
13924     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
13925     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
13926     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
13927     "\n\t\t:       [-noExtensions {0|1}] [-maxVersion Major Minor]"
13928     "\n\t\t: Modify particular graphic driver options:"
13929     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
13930     "\n\t\t:             built-in GLSL programs"
13931     "\n\t\t:            (requires compatible profile)"
13932     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
13933     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
13934     "\n\t\t:             arrays to GPU memory)"
13935     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
13936     "\n\t\t:  vsync    - switch VSync on or off"
13937     "\n\t\t:  winBuffer - allow using window buffer for rendering"
13938     "\n\t\t: Context creation options:"
13939     "\n\t\t:  softMode          - software OpenGL implementation"
13940     "\n\t\t:  compatibleProfile - backward-compatible profile"
13941     "\n\t\t:  quadbuffer        - QuadBuffer"
13942     "\n\t\t:  noExtensions      - disallow usage of extensions"
13943     "\n\t\t:  maxVersion        - force upper OpenGL version to be used"
13944     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13945     "\n\t\t: rendering paths producing the same visual result when"
13946     "\n\t\t: possible."
13947     "\n\t\t: Command is intended for testing old hardware compatibility.",
13948     __FILE__, VCaps, group);
13949   theCommands.Add ("vmemgpu",
13950     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13951     " with f option returns free memory in bytes",
13952     __FILE__, VMemGpu, group);
13953   theCommands.Add ("vreadpixel",
13954     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13955     " : Read pixel value for active view",
13956     __FILE__, VReadPixel, group);
13957   theCommands.Add("diffimage",
13958             "diffimage imageFile1 imageFile2 [diffImageFile]"
13959     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13960     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13961     "\n\t\t: Compare two images by content and generate difference image."
13962     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13963     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13964     __FILE__, VDiffImage, group);
13965   theCommands.Add ("vselect",
13966     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13967     "- emulates different types of selection:\n"
13968     "- 1) single click selection\n"
13969     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13970     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13971     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13972     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13973     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13974     " (partial inclusion - overlap - is not allowed by default)\n"
13975     "- 5) any of these selections with shift button pressed",
13976     __FILE__, VSelect, group);
13977   theCommands.Add ("vmoveto",
13978     "vmoveto [x y] [-reset]"
13979     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13980     "\n\t\t:   -reset resets current highlighting",
13981     __FILE__, VMoveTo, group);
13982   theCommands.Add ("vviewparams",
13983               "vviewparams [-args] [-scale [s]]"
13984       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13985       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13986       "\n\t\t: Manage current view parameters or prints all"
13987       "\n\t\t: current values when called without argument."
13988       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13989       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13990       "\n\t\t:   -at   [x y z] prints or sets center of look"
13991       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13992       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13993       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13994       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13995       "\n\t\t:                 or changes the size of its maximum dimension"
13996       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13997     __FILE__, VViewParams, group);
13998
13999   theCommands.Add("v2dmode",
14000     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
14001     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
14002     "\n\t\t:   mode   - switches On/Off rotation mode"
14003     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
14004     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
14005     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
14006     "\n\t\t: View camera position might be changed only by commands.",
14007     __FILE__, V2DMode, group);
14008
14009   theCommands.Add("vanimation", "Alias for vanim",
14010     __FILE__, VAnimation, group);
14011
14012   theCommands.Add("vanim",
14013             "List existing animations:"
14014     "\n\t\t:  vanim"
14015     "\n\t\t: Animation playback:"
14016     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
14017     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
14018     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
14019     "\n\t\t:   -freeLook skip camera animations"
14020     "\n\t\t:   -lockLoop disable any interactions"
14021     "\n\t\t:"
14022     "\n\t\t: Animation definition:"
14023     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
14024     "\n\t\t:        [start TimeSec] [duration TimeSec]"
14025     "\n\t\t:"
14026     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
14027     "\n\t\t: specifies nested animations."
14028     "\n\t\t: There is no syntax to explicitly add new animation,"
14029     "\n\t\t: and all non-existing animations within the name will be"
14030     "\n\t\t: implicitly created on first use (including parents)."
14031     "\n\t\t:"
14032     "\n\t\t: Each animation might define the SINGLE action (see below),"
14033     "\n\t\t: like camera transition, object transformation or custom callback."
14034     "\n\t\t: Child animations can be used for defining concurrent actions."
14035     "\n\t\t:"
14036     "\n\t\t: Camera animation:"
14037     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
14038     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
14039     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
14040     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
14041     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
14042     "\n\t\t:   -atX    camera Center positions pair"
14043     "\n\t\t:   -upX    camera Up directions pair"
14044     "\n\t\t:   -scaleX camera Scale factors pair"
14045     "\n\t\t: Object animation:"
14046     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
14047     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
14048     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
14049     "\n\t\t:   -locX   object Location points pair (translation)"
14050     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
14051     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
14052     "\n\t\t: Custom callback:"
14053     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
14054     "\n\t\t:   %Pts        overall animation presentation timestamp"
14055     "\n\t\t:   %LocalPts   local animation timestamp"
14056     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
14057     "\n\t\t:"
14058     "\n\t\t: Video recording:"
14059     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
14060     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
14061     "\n\t\t:             [-crf Value] [-preset Preset]"
14062     "\n\t\t:   -fps     video framerate"
14063     "\n\t\t:   -format  file format, container (matroska, etc.)"
14064     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
14065     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
14066     "\n\t\t:   -crf     constant rate factor (specific to codec)"
14067     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
14068     __FILE__, VAnimation, group);
14069
14070   theCommands.Add("vchangeselected",
14071     "vchangeselected shape"
14072     "- adds to shape to selection or remove one from it",
14073                 __FILE__, VChangeSelected, group);
14074   theCommands.Add ("vnbselected",
14075     "vnbselected"
14076     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
14077   theCommands.Add ("vcamera",
14078               "vcamera [PrsName] [-ortho] [-projtype]"
14079       "\n\t\t:         [-persp]"
14080       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
14081       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
14082       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
14083       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
14084       "\n\t\t: Manages camera parameters."
14085       "\n\t\t: Displays frustum when presntation name PrsName is specified."
14086       "\n\t\t: Prints current value when option called without argument."
14087       "\n\t\t: Orthographic camera:"
14088       "\n\t\t:   -ortho      activate orthographic projection"
14089       "\n\t\t: Perspective camera:"
14090       "\n\t\t:   -persp      activate perspective  projection (mono)"
14091       "\n\t\t:   -fovy       field of view in y axis, in degrees"
14092       "\n\t\t:   -distance   distance of eye from camera center"
14093       "\n\t\t: Stereoscopic camera:"
14094       "\n\t\t:   -stereo     perspective  projection (stereo)"
14095       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
14096       "\n\t\t:   -rightEye   perspective  projection (right eye)"
14097       "\n\t\t:   -iod        intraocular distance value"
14098       "\n\t\t:   -iodType    distance type, absolute or relative"
14099       "\n\t\t:   -zfocus     stereographic focus value"
14100       "\n\t\t:   -zfocusType focus type, absolute or relative",
14101     __FILE__, VCamera, group);
14102   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
14103     "- vautozfit [on={1|0}] [scale]\n"
14104     "    Prints or changes parameters of automatic z-fit mode:\n"
14105     "   \"on\" - turns automatic z-fit on or off\n"
14106     "   \"scale\" - specifies factor to scale computed z range.\n",
14107     __FILE__, VAutoZFit, group);
14108   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
14109     "   vzrange                - without parameters shows current values\n"
14110     "   vzrange [znear] [zfar] - applies provided values to view",
14111     __FILE__,VZRange, group);
14112   theCommands.Add ("vpurgedisplay",
14113     "vpurgedisplay"
14114     "- removes structures which don't belong to objects displayed in neutral point",
14115     __FILE__, VPurgeDisplay, group);
14116   theCommands.Add("vsetviewsize",
14117     "vsetviewsize size",
14118     __FILE__,VSetViewSize,group);
14119   theCommands.Add("vmoveview",
14120     "vmoveview Dx Dy Dz [Start = 1|0]",
14121     __FILE__,VMoveView,group);
14122   theCommands.Add("vtranslateview",
14123     "vtranslateview Dx Dy Dz [Start = 1|0)]",
14124     __FILE__,VTranslateView,group);
14125   theCommands.Add("vturnview",
14126     "vturnview Ax Ay Az [Start = 1|0]",
14127     __FILE__,VTurnView,group);
14128   theCommands.Add("vtextureenv",
14129     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
14130     "or user-defined file and optionally applying texture mapping parameters\n"
14131     "                  Usage:\n"
14132     "                  vtextureenv off - disables environment mapping\n"
14133     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
14134     "                              std_texture = (0..7)\n"
14135     "                              rep         = {clamp|repeat}\n"
14136     "                              mod         = {decal|modulate}\n"
14137     "                              flt         = {nearest|bilinear|trilinear}\n"
14138     "                              ss, st      - scale factors for s and t texture coordinates\n"
14139     "                              ts, tt      - translation for s and t texture coordinates\n"
14140     "                              rot         - texture rotation angle in degrees",
14141     __FILE__, VTextureEnv, group);
14142   theCommands.Add("vhlr",
14143             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
14144       "\n\t\t: Hidden Line Removal algorithm."
14145       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
14146       "\n\t\t:   -algoType   type of HLR algorithm.\n",
14147     __FILE__,VHLR,group);
14148   theCommands.Add("vhlrtype",
14149               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
14150       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
14151       "\n\t\t:   'algo' - exact HLR algorithm is applied"
14152       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
14153       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
14154     __FILE__,VHLRType,group);
14155   theCommands.Add("vclipplane",
14156               "vclipplane planeName [{0|1}]"
14157       "\n\t\t:   [-equation1 A B C D]"
14158       "\n\t\t:   [-equation2 A B C D]"
14159       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
14160       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
14161       "\n\t\t:   [-maxPlanes]"
14162       "\n\t\t:   [-capping {0|1}]"
14163       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
14164       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
14165       "\n\t\t:       [-texRotate Angle]"
14166       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
14167       "\n\t\t:       [-useObjShader {0|1}]"
14168       "\n\t\t: Clipping planes management:"
14169       "\n\t\t:   -maxPlanes   print plane limit for view"
14170       "\n\t\t:   -delete      delete plane with given name"
14171       "\n\t\t:   {off|on|0|1} turn clipping on/off"
14172       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
14173       "\n\t\t:                applied to active View when list is omitted"
14174       "\n\t\t:   -equation A B C D change plane equation"
14175       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
14176       "\n\t\t: Capping options:"
14177       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
14178       "\n\t\t:   -color R G B          set capping color"
14179       "\n\t\t:   -transparency Value   set capping transparency 0..1"
14180       "\n\t\t:   -texName Texture      set capping texture"
14181       "\n\t\t:   -texScale SX SY       set capping tex scale"
14182       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
14183       "\n\t\t:   -texRotate Angle      set capping tex rotation"
14184       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
14185       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
14186       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
14187       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
14188       __FILE__, VClipPlane, group);
14189   theCommands.Add("vdefaults",
14190                "vdefaults [-absDefl value]"
14191        "\n\t\t:           [-devCoeff value]"
14192        "\n\t\t:           [-angDefl value]"
14193        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
14194     , __FILE__, VDefaults, group);
14195   theCommands.Add("vlight",
14196     "tool to manage light sources, without arguments shows list of lights."
14197     "\n    Main commands: "
14198     "\n      '-clear' to clear lights"
14199     "\n      '-{def}aults' to load deafault lights"
14200     "\n      '-add' <type> to add any light source"
14201     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
14202     "\n      'change' <lightId> to edit light source with specified lightId"
14203     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
14204     "\n        -layer Id"
14205     "\n        -{pos}ition X Y Z"
14206     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
14207     "\n        -color colorName"
14208     "\n        -{head}light 0|1"
14209     "\n        -{sm}oothness value"
14210     "\n        -{int}ensity value"
14211     "\n        -{constAtten}uation value"
14212     "\n        -{linearAtten}uation value"
14213     "\n        -angle angleDeg"
14214     "\n        -{spotexp}onent value"
14215     "\n        -local|-global"
14216     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
14217     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
14218     __FILE__, VLight, group);
14219   theCommands.Add("vraytrace",
14220             "vraytrace [0|1]"
14221     "\n\t\t: Turns on/off ray-tracing renderer."
14222     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
14223     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
14224     __FILE__, VRenderParams, group);
14225   theCommands.Add("vrenderparams",
14226     "\n    Manages rendering parameters: "
14227     "\n      '-raster'                   Disables GPU ray-tracing"
14228     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
14229     "\n      '-lineFeather  > 0'         Sets line feather factor"
14230     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
14231     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
14232     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
14233     "\n      '-rendScale    value        Rendering resolution scale factor"
14234     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
14235     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
14236     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
14237     "\n      '-reflections  on|off'      Enables/disables specular reflections"
14238     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
14239     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
14240     "\n      '-gi           on|off'      Enables/disables global illumination effects"
14241     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
14242     "\n      '-env          on|off'      Enables/disables environment map background"
14243     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
14244     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
14245     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
14246     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
14247     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
14248     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
14249     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
14250     "\n      '-shadingModel model'       Controls shading model from enumeration"
14251     "\n                                  unlit, flat, gouraud, phong"
14252     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
14253     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
14254     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
14255     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
14256     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
14257     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
14258     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
14259     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
14260     "\n                                  Show/hide performance counters (flags can be combined)"
14261     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
14262     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
14263     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
14264     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
14265     "\n                                        set state to check structures culled previously."
14266     "\n    Unlike vcaps, these parameters dramatically change visual properties."
14267     "\n    Command is intended to control presentation quality depending on"
14268     "\n    hardware capabilities and performance.",
14269     __FILE__, VRenderParams, group);
14270   theCommands.Add("vstatprofiler",
14271     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
14272     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
14273     "\n                |triagles|points|geomMem|textureMem|frameMem"
14274     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
14275     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
14276     "\n                [-noredraw]"
14277     "\n\t\t: Prints rendering statistics."
14278     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
14279     "\n\t\t:   else - print all performance counters set previously."
14280     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
14281     __FILE__, VStatProfiler, group);
14282   theCommands.Add ("vplace",
14283             "vplace dx dy"
14284     "\n\t\t: Places the point (in pixels) at the center of the window",
14285     __FILE__, VPlace, group);
14286   theCommands.Add("vxrotate",
14287     "vxrotate",
14288     __FILE__,VXRotate,group);
14289
14290     theCommands.Add("vmanipulator",
14291       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
14292       "\n    tool to create and manage AIS manipulators."
14293       "\n    Options: "
14294       "\n      '-attach AISObject'                 attach manipulator to AISObject"
14295       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
14296       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
14297       "\n      '-enableModes    {0|1}'             enable modes when attaching"
14298       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
14299       "\n                                          by default it is displayed in all views of the current viewer"
14300       "\n      '-detach'                           detach manipulator"
14301       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
14302       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
14303       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
14304       "\n      '-move x y z'                     - move attached object"
14305       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
14306       "\n      '-scale factor'                   - scale attached object"
14307       "\n      '-autoActivate      {0|1}'        - set activation on detection"
14308       "\n      '-followTranslation {0|1}'        - set following translation transform"
14309       "\n      '-followRotation    {0|1}'        - set following rotation transform"
14310       "\n      '-followDragging    {0|1}'        - set following dragging transform"
14311       "\n      '-gap value'                      - set gap between sub-parts"
14312       "\n      '-part axis mode    {0|1}'        - set visual part"
14313       "\n      '-parts axis mode   {0|1}'        - set visual part"
14314       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
14315       "\n      '-size value'                     - set size of manipulator"
14316       "\n      '-zoomable {0|1}'                 - set zoom persistence",
14317     __FILE__, VManipulator, group);
14318
14319   theCommands.Add("vselprops",
14320     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
14321     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
14322     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
14323     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
14324     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
14325     "\n    -pickStrategy {first|topmost} : defines picking strategy"
14326     "\n                            'first'   to pick first acceptable (default)"
14327     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
14328     "\n    -pixTol    value        : sets up pixel tolerance"
14329     "\n    -dispMode  dispMode     : sets display mode for highlighting"
14330     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
14331     "\n    -color     {name|r g b} : sets highlight color"
14332     "\n    -transp    value        : sets transparency coefficient for highlight"
14333     "\n    -material  material     : sets highlight material"
14334     "\n    -print                  : prints current state of all mentioned parameters",
14335     __FILE__, VSelectionProperties, group);
14336   theCommands.Add ("vhighlightselected",
14337                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
14338                    __FILE__, VSelectionProperties, group);
14339
14340   theCommands.Add ("vseldump",
14341                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
14342                    "\n\t\t: Generate an image based on detection results:"
14343                    "\n\t\t:   depth       normalized depth values"
14344                    "\n\t\t:   unnormDepth unnormalized depth values"
14345                    "\n\t\t:   object      color of detected object"
14346                    "\n\t\t:   owner       color of detected owner"
14347                    "\n\t\t:   selMode     color of selection mode"
14348                    "\n\t\t:   entity      color of etected entity",
14349                    __FILE__, VDumpSelectionImage, group);
14350
14351   theCommands.Add ("vviewcube",
14352                    "vviewcube name"
14353                    "\n\t\t: Displays interactive view manipualtion object."
14354                    "\n\t\t: Options: "
14355                    "\n\t\t:   -reset                   reset geomertical and visual attributes'"
14356                    "\n\t\t:   -size Size               adapted size of View Cube"
14357                    "\n\t\t:   -boxSize Size            box size"
14358                    "\n\t\t:   -axes {0|1 }             show/hide axes (trihedron)"
14359                    "\n\t\t:   -edges {0|1}             show/hide edges of View Cube"
14360                    "\n\t\t:   -vertices {0|1}          show/hide vertices of View Cube"
14361                    "\n\t\t:   -Yup {0|1} -Zup {0|1}    set Y-up or Z-up view orientation"
14362                    "\n\t\t:   -color Color             color of View Cube"
14363                    "\n\t\t:   -boxColor Color          box color"
14364                    "\n\t\t:   -boxSideColor Color      box sides color"
14365                    "\n\t\t:   -boxEdgeColor Color      box edges color"
14366                    "\n\t\t:   -boxCornerColor Color    box corner color"
14367                    "\n\t\t:   -textColor Color         color of side text of view cube"
14368                    "\n\t\t:   -innerColor Color        inner box color"
14369                    "\n\t\t:   -transparency Value      transparency of object within [0, 1] range"
14370                    "\n\t\t:   -boxTransparency Value   transparency of box    within [0, 1] range"
14371                    "\n\t\t:   -font Name               font name"
14372                    "\n\t\t:   -fontHeight Value        font height"
14373                    "\n\t\t:   -boxFacetExtension Value box facet extension"
14374                    "\n\t\t:   -boxEdgeGap Value        gap between box edges and box sides"
14375                    "\n\t\t:   -boxEdgeMinSize Value    minimal box edge size"
14376                    "\n\t\t:   -boxCornerMinSize Value  minimal box corner size"
14377                    "\n\t\t:   -axesPadding Value       padding between box and arrows"
14378                    "\n\t\t:   -roundRadius Value       relative radius of corners of sides within [0.0, 0.5] range"
14379                    "\n\t\t:   -fixedanimation {0|1}    uninterruptible animation loop"
14380                    "\n\t\t:   -duration Seconds        animation duration in seconds",
14381     __FILE__, VViewCube, group);
14382
14383 }