0030806: Visualization - AIS Manipulator highlighting is not affected by the view...
[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_Shape.hxx>
29 #include <Aspect_DisplayConnection.hxx>
30 #include <Aspect_Grid.hxx>
31 #include <Aspect_TypeOfLine.hxx>
32 #include <Draw.hxx>
33 #include <Draw_Appli.hxx>
34 #include <Draw_Interpretor.hxx>
35 #include <Draw_ProgressIndicator.hxx>
36 #include <gp_Dir.hxx>
37 #include <gp_Pln.hxx>
38 #include <gp_Pnt.hxx>
39 #include <Graphic3d_ArrayOfPolylines.hxx>
40 #include <Graphic3d_AspectFillArea3d.hxx>
41 #include <Graphic3d_AspectMarker3d.hxx>
42 #include <Graphic3d_ClipPlane.hxx>
43 #include <Graphic3d_GraduatedTrihedron.hxx>
44 #include <Graphic3d_NameOfTextureEnv.hxx>
45 #include <Graphic3d_Texture2Dmanual.hxx>
46 #include <Graphic3d_TextureEnv.hxx>
47 #include <Graphic3d_TextureParams.hxx>
48 #include <Graphic3d_TypeOfTextureFilter.hxx>
49 #include <Image_AlienPixMap.hxx>
50 #include <Image_Diff.hxx>
51 #include <Image_VideoRecorder.hxx>
52 #include <Message_ProgressSentry.hxx>
53 #include <NCollection_DataMap.hxx>
54 #include <NCollection_List.hxx>
55 #include <NCollection_Vector.hxx>
56 #include <OSD.hxx>
57 #include <OSD_Timer.hxx>
58 #include <OpenGl_GraphicDriver.hxx>
59 #include <Prs3d_ShadingAspect.hxx>
60 #include <Prs3d_Drawer.hxx>
61 #include <Prs3d_LineAspect.hxx>
62 #include <Prs3d_Root.hxx>
63 #include <Prs3d_Text.hxx>
64 #include <Select3D_SensitivePrimitiveArray.hxx>
65 #include <TColStd_HSequenceOfAsciiString.hxx>
66 #include <TColStd_SequenceOfInteger.hxx>
67 #include <TColStd_HSequenceOfReal.hxx>
68 #include <TColgp_Array1OfPnt2d.hxx>
69 #include <TColStd_MapOfAsciiString.hxx>
70 #include <ViewerTest_AutoUpdater.hxx>
71 #include <ViewerTest_EventManager.hxx>
72 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
73 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
74 #include <ViewerTest_CmdParser.hxx>
75 #include <ViewerTest_V3dView.hxx>
76 #include <V3d_AmbientLight.hxx>
77 #include <V3d_DirectionalLight.hxx>
78 #include <V3d_PositionalLight.hxx>
79 #include <V3d_SpotLight.hxx>
80
81 #include <tcl.h>
82
83 #include <cstdlib>
84
85 #if defined(_WIN32)
86   #include <WNT_WClass.hxx>
87   #include <WNT_Window.hxx>
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 //==============================================================================
98 //  VIEWER GLOBAL VARIABLES
99 //==============================================================================
100
101 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
102 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
103
104 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
105 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
106
107 #if defined(_WIN32)
108 static Handle(WNT_Window)& VT_GetWindow() {
109   static Handle(WNT_Window) WNTWin;
110   return WNTWin;
111 }
112 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
113 static Handle(Cocoa_Window)& VT_GetWindow()
114 {
115   static Handle(Cocoa_Window) aWindow;
116   return aWindow;
117 }
118 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
119 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
120
121 #else
122 static Handle(Xw_Window)& VT_GetWindow(){
123   static Handle(Xw_Window) XWWin;
124   return XWWin;
125 }
126
127 static void VProcessEvents(ClientData,int);
128 #endif
129
130 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
131 {
132   static Handle(Aspect_DisplayConnection) aDisplayConnection;
133   return aDisplayConnection;
134 }
135
136 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
137 {
138   GetDisplayConnection() = theDisplayConnection;
139 }
140
141 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
142 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
143 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
144 static OpenGl_Caps ViewerTest_myDefaultCaps;
145
146 static void OSWindowSetup();
147
148 static struct
149 {
150   Quantity_Color FlatColor;
151   Quantity_Color GradientColor1;
152   Quantity_Color GradientColor2;
153   Aspect_GradientFillMethod FillMethod;
154 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
155
156 //==============================================================================
157 //  EVENT GLOBAL VARIABLES
158 //==============================================================================
159
160 Standard_Boolean TheIsAnimating = Standard_False;
161
162 namespace
163 {
164
165   //! Checks if some set is a subset of other set
166   //! @tparam TheSuperSet the type of the superset
167   //! @tparam TheSubSet the type of the subset
168   //! @param theSuperSet the superset
169   //! @param theSubSet the subset to be checked
170   //! @return true if the superset includes subset, or false otherwise
171   template <typename TheSuperSet, typename TheSubSet>
172   static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
173   {
174     return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
175   }
176
177   //! A variable set of keys for command-line options.
178   //! It includes a set of mandatory keys and a set of all possible keys.
179   class CommandOptionKeyVariableSet
180   {
181   public:
182     //! Default constructor
183     CommandOptionKeyVariableSet()
184     {
185     }
186
187     //! Constructor
188     //! @param theMandatoryKeySet the set of the mandatory option keys
189     //! @param theAdditionalKeySet the set of additional options that could be omitted
190     CommandOptionKeyVariableSet (
191       const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
192       const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
193     : myMandatoryKeySet (theMandatoryKeySet)
194     {
195       std::set_union (theMandatoryKeySet.begin(),
196                       theMandatoryKeySet.end(),
197                       theAdditionalKeySet.begin(),
198                       theAdditionalKeySet.end(),
199                       std::inserter (myFullKeySet, myFullKeySet.begin()));
200     }
201
202     //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
203     //! and be contained in the full key set)
204     //! @param theCheckedKeySet the set of option keys to be checked
205     bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
206     {
207       return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
208     }
209
210   private:
211     //! A set of mandatory command-line option keys
212     ViewerTest_CommandOptionKeySet myMandatoryKeySet;
213
214     //! A full set of command-line option keys (includes mandatory and additional option keys)
215     ViewerTest_CommandOptionKeySet myFullKeySet;
216   };
217
218   //! Gets some code by its name
219   //! @tparam TheCode the type of a code to be found
220   //! @param theCodeNameMap the map from code names to codes
221   //! @param theCodeName the name of a code to be found
222   //! @param theCode the code to be found
223   //! @return true if a code is found, or false otherwise
224   template <typename TheCode>
225   static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
226                                  TCollection_AsciiString                           theCodeName,
227                                  TheCode&                                          theCode)
228   {
229     theCodeName.LowerCase();
230     const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
231       theCodeName);
232     if (aCodeIterator == theCodeNameMap.end())
233     {
234       return false;
235     }
236     theCode = aCodeIterator->second;
237     return true;
238   }
239
240   // Defines possible commands related to background changing
241   enum BackgroundCommand
242   {
243     BackgroundCommand_Main,         //!< The main command that manages other commands through options
244     BackgroundCommand_Image,        //!< Sets an image as a background
245     BackgroundCommand_ImageMode,    //!< Changes a background image mode
246     BackgroundCommand_Gradient,     //!< Sets a gradient as a background
247     BackgroundCommand_GradientMode, //!< Changes a background gradient mode
248     BackgroundCommand_Color,        //!< Fills background with a specified color
249     BackgroundCommand_Default       //!< Sets the background default color or gradient
250   };
251
252   //! Map from background command names to its codes
253   typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
254
255   //! Creates a map from background command names to its codes
256   //! @return a map from background command names to its codes
257   static BackgroundCommandNameMap createBackgroundCommandNameMap()
258   {
259     BackgroundCommandNameMap aBackgroundCommandNameMap;
260     aBackgroundCommandNameMap["vbackground"]    = BackgroundCommand_Main;
261     aBackgroundCommandNameMap["vsetbg"]         = BackgroundCommand_Image;
262     aBackgroundCommandNameMap["vsetbgmode"]     = BackgroundCommand_ImageMode;
263     aBackgroundCommandNameMap["vsetgradientbg"] = BackgroundCommand_Gradient;
264     aBackgroundCommandNameMap["vsetgrbgmode"]   = BackgroundCommand_GradientMode;
265     aBackgroundCommandNameMap["vsetcolorbg"]    = BackgroundCommand_Color;
266     aBackgroundCommandNameMap["vsetdefaultbg"]  = BackgroundCommand_Default;
267     return aBackgroundCommandNameMap;
268   }
269
270   //! Gets a background command by its name
271   //! @param theBackgroundCommandName the name of the background command
272   //! @param theBackgroundCommand the background command to be found
273   //! @return true if a background command is found, or false otherwise
274   static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
275                                           BackgroundCommand&             theBackgroundCommand)
276   {
277     static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
278     return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
279   }
280
281   //! Map from background image fill method names to its codes
282   typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
283
284   //! Creates a map from background image fill method names to its codes
285   //! @return a map from background image fill method names to its codes
286   static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
287   {
288     BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
289     aBackgroundImageFillMethodNameMap["none"]     = Aspect_FM_NONE;
290     aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
291     aBackgroundImageFillMethodNameMap["tiled"]    = Aspect_FM_TILED;
292     aBackgroundImageFillMethodNameMap["stretch"]  = Aspect_FM_STRETCH;
293     return aBackgroundImageFillMethodNameMap;
294   }
295
296   //! Gets a background image fill method by its name
297   //! @param theBackgroundImageFillMethodName the name of the background image fill method
298   //! @param theBackgroundImageFillMethod the background image fill method to be found
299   //! @return true if a background image fill method is found, or false otherwise
300   static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
301                                                   Aspect_FillMethod&             theBackgroundImageFillMethod)
302   {
303     static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
304       createBackgroundImageFillMethodNameMap();
305     return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
306                               theBackgroundImageFillMethodName,
307                               theBackgroundImageFillMethod);
308   }
309
310   //! Map from background gradient fill method names to its codes
311   typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
312
313   //! Creates a map from background gradient fill method names to its codes
314   //! @return a map from background gradient fill method names to its codes
315   static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
316   {
317     BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
318     aBackgroundGradientFillMethodNameMap["none"]       = Aspect_GFM_NONE;
319     aBackgroundGradientFillMethodNameMap["hor"]        = Aspect_GFM_HOR;
320     aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
321     aBackgroundGradientFillMethodNameMap["ver"]        = Aspect_GFM_VER;
322     aBackgroundGradientFillMethodNameMap["vertical"]   = Aspect_GFM_VER;
323     aBackgroundGradientFillMethodNameMap["diag1"]      = Aspect_GFM_DIAG1;
324     aBackgroundGradientFillMethodNameMap["diagonal1"]  = Aspect_GFM_DIAG1;
325     aBackgroundGradientFillMethodNameMap["diag2"]      = Aspect_GFM_DIAG2;
326     aBackgroundGradientFillMethodNameMap["diagonal2"]  = Aspect_GFM_DIAG2;
327     aBackgroundGradientFillMethodNameMap["corner1"]    = Aspect_GFM_CORNER1;
328     aBackgroundGradientFillMethodNameMap["corner2"]    = Aspect_GFM_CORNER2;
329     aBackgroundGradientFillMethodNameMap["corner3"]    = Aspect_GFM_CORNER3;
330     aBackgroundGradientFillMethodNameMap["corner4"]    = Aspect_GFM_CORNER4;
331     return aBackgroundGradientFillMethodNameMap;
332   }
333
334   //! Gets a gradient fill method by its name
335   //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
336   //! @param theBackgroundGradientFillMethod the gradient fill method to be found
337   //! @return true if a gradient fill method is found, or false otherwise
338   static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
339                                                      Aspect_GradientFillMethod&     theBackgroundGradientFillMethod)
340   {
341     static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
342       createBackgroundGradientFillMethodNameMap();
343     return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
344                               theBackgroundGradientFillMethodName,
345                               theBackgroundGradientFillMethod);
346   }
347
348   //! Changes the background in accordance with passed command line options
349   class BackgroundChanger
350   {
351   public:
352     //! Constructor. Prepares the command parser
353     BackgroundChanger()
354     {
355       prepareCommandParser();
356     }
357
358     //! Processes the command line and changes the background
359     //! @param theDrawInterpretor the interpreter of the Draw Harness application
360     //! @param theNumberOfCommandLineArguments the number of passed command line arguments
361     //! @param theCommandLineArguments the array of command line arguments
362     bool ProcessCommandLine (Draw_Interpretor&        theDrawInterpretor,
363                              const Standard_Integer   theNumberOfCommandLineArguments,
364                              const char* const* const theCommandLineArguments)
365     {
366       const char* const aBackgroundCommandName = theCommandLineArguments[0];
367       BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
368       if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
369       {
370         return false;
371       }
372       addCommandDescription (aBackgroundCommand);
373       myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
374       return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
375     }
376
377   private:
378     //! The type of functions that are able to set gradient background filling
379     typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
380                                       const Quantity_Color& /* theColor2 */,
381                                       const Aspect_GradientFillMethod /* theGradientMode */);
382
383     //! The type of functions that are able to fill a background with a specific color
384     typedef void SetColorFunction (const Quantity_Color& /* theColor */);
385
386     //! the command parser used to parse command line options and its arguments
387     ViewerTest_CmdParser myCommandParser;
388
389     //! the option key for the command that sets an image as a background
390     ViewerTest_CommandOptionKey myImageOptionKey;
391
392     //! the option key for the command that sets a background image fill type
393     ViewerTest_CommandOptionKey myImageModeOptionKey;
394
395     //! the option key for the command that sets a gradient filling for the background
396     ViewerTest_CommandOptionKey myGradientOptionKey;
397
398     //! the option key for the command that sets a background gradient filling method
399     ViewerTest_CommandOptionKey myGradientModeOptionKey;
400
401     //! the option key for the command that fills background with a specific color
402     ViewerTest_CommandOptionKey myColorOptionKey;
403
404     //! the option key for the command that sets default background gradient or color
405     ViewerTest_CommandOptionKey myDefaultOptionKey;
406
407     //! the variable set of options that are allowed for the old scenario (without any option passed)
408     CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
409
410     //! the variable set of options that are allowed for setting an image as a background
411     CommandOptionKeyVariableSet myImageOptionVariableSet;
412
413     //! the variable set of options that are allowed for setting a background image fill type
414     CommandOptionKeyVariableSet myImageModeOptionVariableSet;
415
416     //! the variable set of options that are allowed for setting a gradient filling for the background
417     CommandOptionKeyVariableSet myGradientOptionVariableSet;
418
419     //! the variable set of options that are allowed for setting a background gradient filling method
420     CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
421
422     //! the variable set of options that are allowed for filling a background with a specific color
423     CommandOptionKeyVariableSet myColorOptionVariableSet;
424
425     //! the variable set of options that are allowed for setting a default background gradient
426     CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
427
428     //! the variable set of options that are allowed for setting a default background color
429     CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
430
431     //! the variable set of options that are allowed for printing help
432     CommandOptionKeyVariableSet myHelpOptionVariableSet;
433
434     //! Adds options to command parser
435     void addOptionsToCommandParser()
436     {
437       myImageOptionKey     = myCommandParser.AddOption ("imageFile|image|imgFile|img",
438                                                     "filename of image used as background");
439       myImageModeOptionKey = myCommandParser.AddOption (
440         "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
441       myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
442                                                        "sets background gradient starting and ending colors");
443       myGradientModeOptionKey =
444         myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
445                                    "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
446                                    "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
447       myColorOptionKey   = myCommandParser.AddOption ("color|col", "background color");
448       myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
449     }
450
451     //! Creates option sets used to determine if a passed option set is valid or not
452     void createOptionSets()
453     {
454       ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
455       anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
456       myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
457
458       ViewerTest_CommandOptionKeySet anImageOptionSet;
459       anImageOptionSet.insert (myImageOptionKey);
460       ViewerTest_CommandOptionKeySet anImageModeOptionSet;
461       anImageModeOptionSet.insert (myImageModeOptionKey);
462       myImageOptionVariableSet     = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
463       myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
464
465       ViewerTest_CommandOptionKeySet aGradientOptionSet;
466       aGradientOptionSet.insert (myGradientOptionKey);
467       ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
468       aGradientModeOptionSet.insert (myGradientModeOptionKey);
469       myGradientOptionVariableSet     = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
470       myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
471
472       ViewerTest_CommandOptionKeySet aColorOptionSet;
473       aColorOptionSet.insert (myColorOptionKey);
474       myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
475
476       aGradientOptionSet.insert (myDefaultOptionKey);
477       myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
478       aColorOptionSet.insert (myDefaultOptionKey);
479       myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
480
481       ViewerTest_CommandOptionKeySet aHelpOptionSet;
482       aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
483       myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
484     }
485
486     //! Prepares the command parser. Adds options and creates option sets used to determine
487     //! if a passed option set is valid or not
488     void prepareCommandParser()
489     {
490       addOptionsToCommandParser();
491       createOptionSets();
492     }
493
494     //! Adds a command description to the command parser
495     //! @param theBackgroundCommand the key of the command which description is added to the command parser
496     void addCommandDescription (const BackgroundCommand theBackgroundCommand)
497     {
498       std::string aDescription;
499       bool        isMainCommand = false;
500       switch (theBackgroundCommand)
501       {
502         case BackgroundCommand_Main:
503           aDescription  = "Command: vbackground (changes background or some background settings)";
504           isMainCommand = true;
505           break;
506         case BackgroundCommand_Image:
507           aDescription = "Command: vsetbg (loads image as a background)";
508           break;
509         case BackgroundCommand_ImageMode:
510           aDescription = "Command: vsetbgmode (changes background fill type)";
511           break;
512         case BackgroundCommand_Gradient:
513           aDescription = "Command: vsetgradientbg (mounts gradient background)";
514           break;
515         case BackgroundCommand_GradientMode:
516           aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
517           break;
518         case BackgroundCommand_Color:
519           aDescription = "Command: vsetcolorbg (sets color background)";
520           break;
521         case BackgroundCommand_Default:
522           aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
523           break;
524         default:
525           return;
526       }
527       if (!isMainCommand)
528       {
529         aDescription += "\nThis command is obsolete. Use vbackground instead.";
530       }
531       myCommandParser.SetDescription (aDescription);
532     }
533
534     //! Check if a viewer is needed to be initialized
535     //! @param theBackgroundCommand the key of the command that changes the background
536     //! @return true if processing was successful, or false otherwise
537     bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
538     {
539       const bool                           isMain             = (theBackgroundCommand == BackgroundCommand_Main);
540       const ViewerTest_CommandOptionKeySet aUsedOptions       = myCommandParser.GetUsedOptions();
541       const bool                           aViewerIsNotNeeded =
542         (theBackgroundCommand == BackgroundCommand_Default)
543         || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
544         || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
545         || myHelpOptionVariableSet.IsInSet (aUsedOptions);
546       return !aViewerIsNotNeeded;
547     }
548
549     //! Check if a viewer is initialized
550     //! @param theBackgroundCommandName the name of the command that changes the background
551     //! @param theDrawInterpretor the interpreter of the Draw Harness application
552     //! @return true if a viewer is initialized, or false otherwise
553     static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
554                                           Draw_Interpretor& theDrawInterpretor)
555     {
556       const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
557       if (anAISContext.IsNull())
558       {
559         theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
560         return false;
561       }
562       return true;
563     }
564
565     //! Processes command options
566     //! @param theBackgroundCommandName the name of the command that changes the background
567     //! @param theBackgroundCommand the key of the command that changes the background
568     //! @param theDrawInterpretor the interpreter of the Draw Harness application
569     //! @return true if processing was successful, or false otherwise
570     bool processCommandOptions (const char* const       theBackgroundCommandName,
571                                 const BackgroundCommand theBackgroundCommand,
572                                 Draw_Interpretor&       theDrawInterpretor) const
573     {
574       if (myCommandParser.HasNoOption())
575       {
576         return printHelp (theBackgroundCommandName, theDrawInterpretor);
577       }
578       if (checkViewerIsNeeded (theBackgroundCommand)
579           && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
580       {
581         return false;
582       }
583       if (myCommandParser.HasOnlyUnnamedOption())
584       {
585         return processUnnamedOption (theBackgroundCommand);
586       }
587       return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
588     }
589
590     //! Processes the unnamed option
591     //! @param theBackgroundCommand the key of the command that changes the background
592     //! @return true if processing was successful, or false otherwise
593     bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
594     {
595       switch (theBackgroundCommand)
596       {
597         case BackgroundCommand_Main:
598           return false;
599         case BackgroundCommand_Image:
600           return processImageUnnamedOption();
601         case BackgroundCommand_ImageMode:
602           return processImageModeUnnamedOption();
603         case BackgroundCommand_Gradient:
604           return processGradientUnnamedOption();
605         case BackgroundCommand_GradientMode:
606           return processGradientModeUnnamedOption();
607         case BackgroundCommand_Color:
608           return processColorUnnamedOption();
609         case BackgroundCommand_Default:
610           return processDefaultUnnamedOption();
611         default:
612           return false;
613       }
614     }
615
616     //! Processes the image unnamed option
617     //! @return true if processing was successful, or false otherwise
618     bool processImageUnnamedOption() const
619     {
620       const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
621         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
622       if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
623       {
624         return false;
625       }
626       std::string anImageFileName;
627       if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
628       {
629         return false;
630       }
631       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
632       if (aNumberOfImageUnnamedOptionArguments == 2)
633       {
634         std::string anImageModeString;
635         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
636         {
637           return false;
638         }
639         if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
640         {
641           return false;
642         }
643       }
644       setImage (anImageFileName.c_str(), anImageMode);
645       return true;
646     }
647
648     //! Processes the image mode unnamed option
649     //! @return true if processing was successful, or false otherwise
650     bool processImageModeUnnamedOption() const
651     {
652       return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
653     }
654
655     //! Processes the gradient unnamed option
656     //! @param theSetGradient the function used to set a background gradient filling
657     //! @return true if processing was successful, or false otherwise
658     bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
659     {
660       const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
661         ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
662       if (aNumberOfGradientUnnamedOptionArguments < 2)
663       {
664         return false;
665       }
666
667       Standard_Integer anArgumentIndex = 0;
668       Quantity_Color   aColor1;
669       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
670       {
671         return false;
672       }
673       if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
674       {
675         return false;
676       }
677
678       Quantity_Color aColor2;
679       if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
680       {
681         return false;
682       }
683       if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
684       {
685         return false;
686       }
687
688       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
689       if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
690       {
691         std::string anGradientModeString;
692
693         if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
694                                   anArgumentIndex,
695                                   anGradientModeString))
696         {
697           return false;
698         }
699         if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
700         {
701           return false;
702         }
703         ++anArgumentIndex;
704       }
705       if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
706       {
707         return false;
708       }
709       theSetGradient (aColor1, aColor2, aGradientMode);
710       return true;
711     }
712
713     //! Processes the gradient mode unnamed option
714     //! @return true if processing was successful, or false otherwise
715     bool processGradientModeUnnamedOption() const
716     {
717       return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
718     }
719
720     //! Processes the color unnamed option
721     //! @param theSetColor the function used to set a background color
722     //! @return true if processing was successful, or false otherwise
723     bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
724     {
725       return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
726     }
727
728     //! Processes the default back unnamed option
729     //! @return true if processing was successful, or false otherwise
730     bool processDefaultUnnamedOption() const
731     {
732       if (processGradientUnnamedOption (setDefaultGradient))
733       {
734         return true;
735       }
736       return processColorUnnamedOption (setDefaultColor);
737     }
738
739     //! Processes named options
740     //! @param theBackgroundCommandName the name of the command that changes the background
741     //! @param theBackgroundCommand the key of the command that changes the background
742     //! @param theDrawInterpretor the interpreter of the Draw Harness application
743     //! @return true if processing was successful, or false otherwise
744     bool processNamedOptions (const char* const       theBackgroundCommandName,
745                               const BackgroundCommand theBackgroundCommand,
746                               Draw_Interpretor&       theDrawInterpretor) const
747     {
748       const bool                           isMain       = (theBackgroundCommand == BackgroundCommand_Main);
749       const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
750       if (myImageOptionVariableSet.IsInSet (aUsedOptions)
751           && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
752       {
753         return processImageOptionSet();
754       }
755       if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
756           && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
757       {
758         return processImageModeOptionSet();
759       }
760       if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
761           && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
762       {
763         return processGradientOptionSet();
764       }
765       if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
766           && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
767       {
768         return processGradientModeOptionSet();
769       }
770       if (myColorOptionVariableSet.IsInSet (aUsedOptions)
771           && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
772       {
773         return processColorOptionSet();
774       }
775       if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
776           || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
777               && (theBackgroundCommand == BackgroundCommand_Default)))
778       {
779         return processDefaultGradientOptionSet();
780       }
781       if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
782           || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
783       {
784         return processDefaultColorOptionSet();
785       }
786       if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
787       {
788         return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
789       }
790       return false;
791     }
792
793     //! Processes the image option set
794     //! @return true if processing was successful, or false otherwise
795     bool processImageOptionSet() const
796     {
797       std::string anImageFileName;
798       if (!processImageOption (anImageFileName))
799       {
800         return false;
801       }
802       Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
803       if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
804       {
805         return false;
806       }
807       setImage (anImageFileName.c_str(), anImageMode);
808       return true;
809     }
810
811     //! Processes the image mode option set
812     //! @return true if processing was successful, or false otherwise
813     bool processImageModeOptionSet() const
814     {
815       return processImageModeOptionSet (myImageModeOptionKey);
816     }
817
818     //! Processes the image mode option set
819     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
820     //! @return true if processing was successful, or false otherwise
821     bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
822     {
823       Aspect_FillMethod anImageMode = Aspect_FM_NONE;
824       if (!processImageModeOption (theImageModeOptionKey, anImageMode))
825       {
826         return false;
827       }
828       setImageMode (anImageMode);
829       return true;
830     }
831
832     //! Processes the gradient option set
833     //! @param theSetGradient the function used to set a background gradient filling
834     //! @return true if processing was successful, or false otherwise
835     bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
836     {
837       Quantity_Color aColor1;
838       Quantity_Color aColor2;
839       if (!processGradientOption (aColor1, aColor2))
840       {
841         return false;
842       }
843       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
844       if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
845       {
846         return false;
847       }
848       theSetGradient (aColor1, aColor2, aGradientMode);
849       return true;
850     }
851
852     //! Processes the gradient mode option set
853     //! @return true if processing was successful, or false otherwise
854     bool processGradientModeOptionSet() const
855     {
856       return processGradientModeOptionSet (myGradientModeOptionKey);
857     }
858
859     //! Processes the gradient mode option set
860     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
861     //! @return true if processing was successful, or false otherwise
862     bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
863     {
864       Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
865       if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
866       {
867         return false;
868       }
869       setGradientMode (aGradientMode);
870       return true;
871     }
872
873     //! Processes the color option set
874     //! @param theSetColor the function used to set a background color
875     //! @return true if processing was successful, or false otherwise
876     bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
877     {
878       return processColorOptionSet (myColorOptionKey, theSetColor);
879     }
880
881     //! Processes the default color option set
882     //! @return true if processing was successful, or false otherwise
883     bool processDefaultGradientOptionSet() const
884     {
885       return processGradientOptionSet (setDefaultGradient);
886     }
887
888     //! Processes the default gradient option set
889     //! @return true if processing was successful, or false otherwise
890     bool processDefaultColorOptionSet() const
891     {
892       return processColorOptionSet (setDefaultColor);
893     }
894
895     //! Processes the color option set
896     //! @param theColorOptionKey the key of the option that is interpreted as a color option
897     //! @param theSetColor the function used to set a background color
898     //! @return true if processing was successful, or false otherwise
899     bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
900                                 SetColorFunction* const           theSetColor = setColor) const
901     {
902       Quantity_Color aColor;
903       if (!processColorOption (theColorOptionKey, aColor))
904       {
905         return false;
906       }
907       theSetColor (aColor);
908       return true;
909     }
910
911     //! Processes the help option set
912     //! @param theBackgroundCommandName the name of the command that changes the background
913     //! @param theDrawInterpretor the interpreter of the Draw Harness application
914     //! @return true if processing was successful, or false otherwise
915     bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
916     {
917       const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
918         ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
919       if (aNumberOfHelpOptionArguments != 0)
920       {
921         return false;
922       }
923       return printHelp (theBackgroundCommandName, theDrawInterpretor);
924     }
925
926     //! Processes the image option
927     //! @param theImageFileName the filename of the image to be used as a background
928     //! @return true if processing was successful, or false otherwise
929     bool processImageOption (std::string& theImageFileName) const
930     {
931       const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
932         myImageOptionKey);
933       if (aNumberOfImageOptionArguments != 1)
934       {
935         return false;
936       }
937       std::string anImageFileName;
938       if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
939       {
940         return false;
941       }
942       theImageFileName = anImageFileName;
943       return true;
944     }
945
946     //! Processes the image mode option
947     //! @param theImageMode the fill type used for a background image
948     //! @return true if processing was successful, or false otherwise
949     bool processImageModeOption (Aspect_FillMethod& theImageMode) const
950     {
951       return processImageModeOption (myImageModeOptionKey, theImageMode);
952     }
953
954     //! Processes the image mode option
955     //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
956     //! @param theImageMode the fill type used for a background image
957     //! @return true if processing was successful, or false otherwise
958     bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
959                                  Aspect_FillMethod&                theImageMode) const
960     {
961       return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
962     }
963
964     //! Processes the gradient option
965     //! @param theColor1 the gradient starting color
966     //! @param theColor2 the gradient ending color
967     //! @return true if processing was successful, or false otherwise
968     bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
969     {
970       Standard_Integer anArgumentIndex = 0;
971       Quantity_Color   aColor1;
972       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
973       {
974         return false;
975       }
976       Quantity_Color aColor2;
977       if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
978       {
979         return false;
980       }
981       const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
982         myGradientOptionKey);
983       if (anArgumentIndex != aNumberOfGradientOptionArguments)
984       {
985         return false;
986       }
987       theColor1 = aColor1;
988       theColor2 = aColor2;
989       return true;
990     }
991
992     //! Processes the gradient mode option
993     //! @param theGradientMode the fill method used for a background gradient filling
994     //! @return true if processing was successful, or false otherwise
995     bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
996     {
997       return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
998     }
999
1000     //! Processes the gradient mode option
1001     //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1002     //! @param theGradientMode the fill method used for a background gradient filling
1003     //! @return true if processing was successful, or false otherwise
1004     bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1005                                     Aspect_GradientFillMethod&        theGradientMode) const
1006     {
1007       return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1008     }
1009
1010     //! Processes some mode option
1011     //! @tparam TheMode the type of a mode to be processed
1012     //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1013     //! @param theMode a mode to be processed
1014     //! @return true if processing was successful, or false otherwise
1015     template <typename TheMode>
1016     bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1017                             bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1018                                                             TheMode& /* theMode */),
1019                             TheMode& theMode) const
1020     {
1021       const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1022         theModeOptionKey);
1023       if (aNumberOfModeOptionArguments != 1)
1024       {
1025         return false;
1026       }
1027       std::string aModeString;
1028       if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1029       {
1030         return false;
1031       }
1032       TheMode aMode = TheMode();
1033       if (!theGetModeByName (aModeString.c_str(), aMode))
1034       {
1035         return false;
1036       }
1037       theMode = aMode;
1038       return true;
1039     }
1040
1041     //! Processes the color option
1042     //! @param theColor a color used for filling a background
1043     //! @return true if processing was successful, or false otherwise
1044     bool processColorOption (Quantity_Color& theColor) const
1045     {
1046       return processColorOption (myColorOptionKey, theColor);
1047     }
1048
1049     //! Processes the color option
1050     //! @param theColorOptionKey the key of the option that is interpreted as a color option
1051     //! @param theColor a color used for filling a background
1052     //! @return true if processing was successful, or false otherwise
1053     bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1054     {
1055       Standard_Integer anArgumentIndex = 0;
1056       Quantity_Color   aColor;
1057       if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1058       {
1059         return false;
1060       }
1061       const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1062         theColorOptionKey);
1063       if (anArgumentIndex != aNumberOfColorOptionArguments)
1064       {
1065         return false;
1066       }
1067       theColor = aColor;
1068       return true;
1069     }
1070
1071     //! Prints helping message
1072     //! @param theBackgroundCommandName the name of the command that changes the background
1073     //! @param theDrawInterpretor the interpreter of the Draw Harness application
1074     //! @return true if printing was successful, or false otherwise
1075     static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1076     {
1077       return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1078     }
1079
1080     //! Sets the image as a background
1081     //! @param theImageFileName the filename of the image to be used as a background
1082     //! @param theImageMode the fill type used for a background image
1083     static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1084     {
1085       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1086       aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1087     }
1088
1089     //! Sets the fill type used for a background image
1090     //! @param theImageMode the fill type used for a background image
1091     static void setImageMode (const Aspect_FillMethod theImageMode)
1092     {
1093       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1094       aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1095     }
1096
1097     //! Sets the gradient filling for a background
1098     //! @param theColor1 the gradient starting color
1099     //! @param theColor2 the gradient ending color
1100     //! @param theGradientMode the fill method used for a background gradient filling
1101     static void setGradient (const Quantity_Color&           theColor1,
1102                              const Quantity_Color&           theColor2,
1103                              const Aspect_GradientFillMethod theGradientMode)
1104     {
1105       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1106       aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1107     }
1108
1109     //! Sets the fill method used for a background gradient filling
1110     //! @param theGradientMode the fill method used for a background gradient filling
1111     static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1112     {
1113       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1114       aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1115     }
1116
1117     //! Sets the color used for filling a background
1118     //! @param theColor the color used for filling a background
1119     static void setColor (const Quantity_Color& theColor)
1120     {
1121       const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1122       aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1123       aCurrentView->SetBackgroundColor (theColor);
1124       aCurrentView->Update();
1125     }
1126
1127     //! Sets the gradient filling for a background in a default viewer
1128     //! @param theColor1 the gradient starting color
1129     //! @param theColor2 the gradient ending color
1130     //! @param theGradientMode the fill method used for a background gradient filling
1131     static void setDefaultGradient (const Quantity_Color&           theColor1,
1132                                     const Quantity_Color&           theColor2,
1133                                     const Aspect_GradientFillMethod theGradientMode)
1134     {
1135       ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1136       ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1137       ViewerTest_DefaultBackground.FillMethod     = theGradientMode;
1138       setDefaultGradient();
1139     }
1140
1141     //! Sets the color used for filling a background in a default viewer
1142     //! @param theColor the color used for filling a background
1143     static void setDefaultColor (const Quantity_Color& theColor)
1144     {
1145       ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1146       ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1147       ViewerTest_DefaultBackground.FillMethod     = Aspect_GFM_NONE;
1148       ViewerTest_DefaultBackground.FlatColor      = theColor;
1149       setDefaultGradient();
1150       setDefaultColor();
1151     }
1152
1153     //! Sets the gradient filling for a background in a default viewer.
1154     //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1155     static void setDefaultGradient()
1156     {
1157       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1158              anInteractiveContextIterator (ViewerTest_myContexts);
1159            anInteractiveContextIterator.More();
1160            anInteractiveContextIterator.Next())
1161       {
1162         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1163         aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1164                                              ViewerTest_DefaultBackground.GradientColor2,
1165                                              ViewerTest_DefaultBackground.FillMethod);
1166       }
1167     }
1168
1169     //! Sets the color used for filling a background in a default viewer.
1170     //! The color value is taken from ViewerTest_DefaultBackground structure
1171     static void setDefaultColor()
1172     {
1173       for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1174              anInteractiveContextIterator (ViewerTest_myContexts);
1175            anInteractiveContextIterator.More();
1176            anInteractiveContextIterator.Next())
1177       {
1178         const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1179         aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1180       }
1181     }
1182   };
1183
1184 } // namespace
1185
1186 typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
1187
1188 Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
1189 {
1190   static ViewerTest_MapOfAISManipulators aMap;
1191   return aMap;
1192 }
1193
1194 Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
1195 {
1196   ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
1197   for (; anIt.More(); anIt.Next())
1198   {
1199     if (anIt.Value()->HasActiveMode())
1200     {
1201       return anIt.Value();
1202     }
1203   }
1204   return NULL;
1205 }
1206
1207 //==============================================================================
1208
1209 #ifdef _WIN32
1210 static LRESULT WINAPI ViewerWindowProc(
1211                                        HWND hwnd,
1212                                        UINT uMsg,
1213                                        WPARAM wParam,
1214                                        LPARAM lParam );
1215 static LRESULT WINAPI AdvViewerWindowProc(
1216   HWND hwnd,
1217   UINT uMsg,
1218   WPARAM wParam,
1219   LPARAM lParam );
1220 #endif
1221
1222
1223 //==============================================================================
1224 //function : WClass
1225 //purpose  :
1226 //==============================================================================
1227
1228 const Handle(Standard_Transient)& ViewerTest::WClass()
1229 {
1230   static Handle(Standard_Transient) theWClass;
1231 #if defined(_WIN32)
1232   if (theWClass.IsNull())
1233   {
1234     theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1235                                 CS_VREDRAW | CS_HREDRAW, 0, 0,
1236                                 ::LoadCursor (NULL, IDC_ARROW));
1237   }
1238 #endif
1239   return theWClass;
1240 }
1241
1242 //==============================================================================
1243 //function : CreateName
1244 //purpose  : Create numerical name for new object in theMap
1245 //==============================================================================
1246 template <typename ObjectType>
1247 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1248                                     const TCollection_AsciiString& theDefaultString)
1249 {
1250   if (theObjectMap.IsEmpty())
1251     return theDefaultString + TCollection_AsciiString(1);
1252
1253   Standard_Integer aNextKey = 1;
1254   Standard_Boolean isFound = Standard_False;
1255   while (!isFound)
1256   {
1257     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1258     // Look for objects with default names
1259     if (theObjectMap.IsBound1(aStringKey))
1260     {
1261       aNextKey++;
1262     }
1263     else
1264       isFound = Standard_True;
1265   }
1266
1267   return theDefaultString + TCollection_AsciiString(aNextKey);
1268 }
1269
1270 //==============================================================================
1271 //structure : ViewerTest_Names
1272 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
1273 //==============================================================================
1274 struct ViewerTest_Names
1275 {
1276 private:
1277   TCollection_AsciiString myDriverName;
1278   TCollection_AsciiString myViewerName;
1279   TCollection_AsciiString myViewName;
1280
1281 public:
1282
1283   const TCollection_AsciiString& GetDriverName () const
1284   {
1285     return myDriverName;
1286   }
1287   void SetDriverName (const TCollection_AsciiString& theDriverName)
1288   {
1289     myDriverName = theDriverName;
1290   }
1291   const TCollection_AsciiString& GetViewerName () const
1292   {
1293     return myViewerName;
1294   }
1295   void SetViewerName (const TCollection_AsciiString& theViewerName)
1296   {
1297     myViewerName = theViewerName;
1298   }
1299   const TCollection_AsciiString& GetViewName () const
1300   {
1301     return myViewName;
1302   }
1303   void SetViewName (const TCollection_AsciiString& theViewName)
1304   {
1305     myViewName = theViewName;
1306   }
1307
1308   //===========================================================================
1309   //function : Constructor for ViewerTest_Names
1310   //purpose  : Get view, viewer, driver names from custom string
1311   //===========================================================================
1312
1313   ViewerTest_Names (const TCollection_AsciiString& theInputString)
1314   {
1315     TCollection_AsciiString aName(theInputString);
1316     if (theInputString.IsEmpty())
1317     {
1318       // Get current configuration
1319       if (ViewerTest_myDrivers.IsEmpty())
1320         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1321           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1322       else
1323         myDriverName = ViewerTest_myDrivers.Find2
1324         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1325
1326       if(ViewerTest_myContexts.IsEmpty())
1327       {
1328         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1329           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1330       }
1331       else
1332       {
1333         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1334       }
1335
1336       myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1337     }
1338     else
1339     {
1340       // There is at least view name
1341       Standard_Integer aParserNumber = 0;
1342       for (Standard_Integer i = 0; i < 3; ++i)
1343       {
1344         Standard_Integer aParserPos = aName.SearchFromEnd("/");
1345         if(aParserPos != -1)
1346         {
1347           aParserNumber++;
1348           aName.Split(aParserPos-1);
1349         }
1350         else
1351           break;
1352       }
1353       if (aParserNumber == 0)
1354       {
1355         // Only view name
1356         if (!ViewerTest::GetAISContext().IsNull())
1357         {
1358           myDriverName = ViewerTest_myDrivers.Find2
1359           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1360           myViewerName = ViewerTest_myContexts.Find2
1361           (ViewerTest::GetAISContext());
1362         }
1363         else
1364         {
1365           // There is no opened contexts here, need to create names for viewer and driver
1366           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1367             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1368
1369           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1370             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1371         }
1372         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1373       }
1374       else if (aParserNumber == 1)
1375       {
1376         // Here is viewerName/viewName
1377         if (!ViewerTest::GetAISContext().IsNull())
1378           myDriverName = ViewerTest_myDrivers.Find2
1379           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1380         else
1381         {
1382           // There is no opened contexts here, need to create name for driver
1383           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1384             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1385         }
1386         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1387
1388         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1389       }
1390       else
1391       {
1392         //Here is driverName/viewerName/viewName
1393         myDriverName = TCollection_AsciiString(aName);
1394
1395         TCollection_AsciiString aViewerName(theInputString);
1396         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1397         myViewerName = TCollection_AsciiString(aViewerName);
1398
1399         myViewName = TCollection_AsciiString(theInputString);
1400       }
1401     }
1402   }
1403 };
1404
1405 //==============================================================================
1406 //function : FindContextByView
1407 //purpose  : Find AIS_InteractiveContext by View
1408 //==============================================================================
1409
1410 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1411 {
1412   Handle(AIS_InteractiveContext) anAISContext;
1413
1414   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1415        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1416   {
1417     if (anIter.Value()->CurrentViewer() == theView->Viewer())
1418        return anIter.Key2();
1419   }
1420   return anAISContext;
1421 }
1422
1423 //==============================================================================
1424 //function : IsWindowOverlapped
1425 //purpose  : Check if theWindow overlapp another view
1426 //==============================================================================
1427
1428 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1429                                      const Standard_Integer thePxTop,
1430                                      const Standard_Integer thePxRight,
1431                                      const Standard_Integer thePxBottom,
1432                                      TCollection_AsciiString& theViewId)
1433 {
1434   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1435       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1436   {
1437     Standard_Integer aTop = 0,
1438       aLeft = 0,
1439       aRight = 0,
1440       aBottom = 0;
1441     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1442     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1443         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1444         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1445         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1446     {
1447       theViewId = anIter.Key1();
1448       return Standard_True;
1449     }
1450   }
1451   return Standard_False;
1452 }
1453
1454 // Workaround: to create and delete non-orthographic views outside ViewerTest
1455 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1456 {
1457   ViewerTest_myViews.UnBind1 (theName);
1458 }
1459
1460 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1461                                const Handle(V3d_View)& theView)
1462 {
1463   ViewerTest_myViews.Bind (theName, theView);
1464 }
1465
1466 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1467 {
1468   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1469 }
1470
1471 //! Auxiliary tool performing continuous redraws of specified window.
1472 class ViewerTest_ContinuousRedrawer
1473 {
1474 public:
1475   //! Return global instance.
1476   static ViewerTest_ContinuousRedrawer& Instance()
1477   {
1478     static ViewerTest_ContinuousRedrawer aRedrawer;
1479     return aRedrawer;
1480   }
1481 public:
1482
1483   //! Destructor.
1484   ~ViewerTest_ContinuousRedrawer()
1485   {
1486     Stop();
1487   }
1488
1489   //! Start thread.
1490   void Start (const Handle(Aspect_Window)& theWindow,
1491               Standard_Real theTargetFps)
1492   {
1493     if (myWindow != theWindow
1494      || myTargetFps != theTargetFps)
1495     {
1496       Stop();
1497       myWindow = theWindow;
1498       myTargetFps = theTargetFps;
1499     }
1500     if (myThread.GetId() == 0)
1501     {
1502       myToStop = false;
1503       myThread.Run (this);
1504     }
1505   }
1506
1507   //! Stop thread.
1508   void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1509   {
1510     if (!theWindow.IsNull()
1511       && myWindow != theWindow)
1512     {
1513       return;
1514     }
1515
1516     {
1517       Standard_Mutex::Sentry aLock (myMutex);
1518       myToStop = true;
1519     }
1520     myThread.Wait();
1521     myToStop = false;
1522     myWindow.Nullify();
1523   }
1524
1525 private:
1526
1527   //! Thread loop.
1528   void doThreadLoop()
1529   {
1530     Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1531     OSD_Timer aTimer;
1532     aTimer.Start();
1533     Standard_Real aTimeOld = 0.0;
1534     const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1535     for (;;)
1536     {
1537       {
1538         Standard_Mutex::Sentry aLock (myMutex);
1539         if (myToStop)
1540         {
1541           return;
1542         }
1543       }
1544       if (myTargetFps > 0.0)
1545       {
1546         const Standard_Real aTimeNew  = aTimer.ElapsedTime();
1547         const Standard_Real aDuration = aTimeNew - aTimeOld;
1548         if (aDuration >= aTargetDur)
1549         {
1550           myWindow->InvalidateContent (aDisp);
1551           aTimeOld = aTimeNew;
1552         }
1553       }
1554       else
1555       {
1556         myWindow->InvalidateContent (aDisp);
1557       }
1558
1559       OSD::MilliSecSleep (1);
1560     }
1561   }
1562
1563   //! Thread creation callback.
1564   static Standard_Address doThreadWrapper (Standard_Address theData)
1565   {
1566     ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1567     aThis->doThreadLoop();
1568     return 0;
1569   }
1570
1571   //! Empty constructor.
1572   ViewerTest_ContinuousRedrawer()
1573   : myThread (doThreadWrapper),
1574     myTargetFps (0.0),
1575     myToStop (false) {}
1576
1577 private:
1578   Handle(Aspect_Window) myWindow;
1579   OSD_Thread      myThread;
1580   Standard_Mutex  myMutex;
1581   Standard_Real   myTargetFps;
1582   volatile bool   myToStop;
1583 };
1584
1585 //==============================================================================
1586 //function : ViewerInit
1587 //purpose  : Create the window viewer and initialize all the global variable
1588 //==============================================================================
1589
1590 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1591                                                 const Standard_Integer thePxTop,
1592                                                 const Standard_Integer thePxWidth,
1593                                                 const Standard_Integer thePxHeight,
1594                                                 const TCollection_AsciiString& theViewName,
1595                                                 const TCollection_AsciiString& theDisplayName,
1596                                                 const Handle(V3d_View)& theViewToClone)
1597 {
1598   // Default position and dimension of the viewer window.
1599   // Note that left top corner is set to be sufficiently small to have
1600   // window fit in the small screens (actual for remote desktops, see #23003).
1601   // The position corresponds to the window's client area, thus some
1602   // gap is added for window frame to be visible.
1603   Standard_Integer aPxLeft   = 20;
1604   Standard_Integer aPxTop    = 40;
1605   Standard_Integer aPxWidth  = 409;
1606   Standard_Integer aPxHeight = 409;
1607   Standard_Boolean toCreateViewer = Standard_False;
1608   if (!theViewToClone.IsNull())
1609   {
1610     theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1611   }
1612
1613   Handle(OpenGl_GraphicDriver) aGraphicDriver;
1614   ViewerTest_Names aViewNames(theViewName);
1615   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1616     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1617
1618   if (thePxLeft != 0)
1619     aPxLeft = thePxLeft;
1620   if (thePxTop != 0)
1621     aPxTop = thePxTop;
1622   if (thePxWidth != 0)
1623     aPxWidth = thePxWidth;
1624   if (thePxHeight != 0)
1625     aPxHeight = thePxHeight;
1626
1627   // Get graphic driver (create it or get from another view)
1628   const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1629   if (isNewDriver)
1630   {
1631     // Get connection string
1632   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1633     if (!theDisplayName.IsEmpty())
1634     {
1635       SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1636     }
1637     else
1638     {
1639       ::Display* aDispX = NULL;
1640       // create dedicated display connection instead of reusing Tk connection
1641       // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1642       /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1643       Tcl_Interp* aTclInterp = aCommands.Interp();
1644       Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1645       aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1646       SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1647     }
1648   #else
1649     (void)theDisplayName; // avoid warning on unused argument
1650     SetDisplayConnection (new Aspect_DisplayConnection ());
1651   #endif
1652
1653     if (Draw_VirtualWindows)
1654     {
1655       // don't waste the time waiting for VSync when window is not displayed on the screen
1656       ViewerTest_myDefaultCaps.swapInterval = 0;
1657       // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1658       //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1659     }
1660     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
1661     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1662
1663     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1664     toCreateViewer = Standard_True;
1665   }
1666   else
1667   {
1668     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1669   }
1670
1671   //Dispose the window if input parameters are default
1672   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1673   {
1674     Standard_Integer aTop = 0,
1675                      aLeft = 0,
1676                      aRight = 0,
1677                      aBottom = 0,
1678                      aScreenWidth = 0,
1679                      aScreenHeight = 0;
1680
1681     // Get screen resolution
1682 #if defined(_WIN32) || defined(__WIN32__)
1683     RECT aWindowSize;
1684     GetClientRect(GetDesktopWindow(), &aWindowSize);
1685     aScreenHeight = aWindowSize.bottom;
1686     aScreenWidth = aWindowSize.right;
1687 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1688     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1689 #else
1690     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1691     aScreenWidth = WidthOfScreen(aScreen);
1692     aScreenHeight = HeightOfScreen(aScreen);
1693 #endif
1694
1695     TCollection_AsciiString anOverlappedViewId("");
1696
1697     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1698     {
1699       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1700
1701       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1702         && aRight + 2*aPxWidth + 40 > aScreenWidth)
1703       {
1704         if (aBottom + aPxHeight + 40 > aScreenHeight)
1705         {
1706           aPxLeft = 20;
1707           aPxTop = 40;
1708           break;
1709         }
1710         aPxLeft = 20;
1711         aPxTop = aBottom + 40;
1712       }
1713       else
1714         aPxLeft = aRight + 20;
1715     }
1716   }
1717
1718   // Get viewer name
1719   TCollection_AsciiString aTitle("3D View - ");
1720   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1721
1722   // Change name of current active window
1723   if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
1724   {
1725     aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
1726   }
1727
1728   // Create viewer
1729   Handle(V3d_Viewer) a3DViewer;
1730   // If it's the single view, we first look for empty context
1731   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1732   {
1733     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1734       anIter(ViewerTest_myContexts);
1735     if (anIter.More())
1736       ViewerTest::SetAISContext (anIter.Value());
1737     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1738   }
1739   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1740   {
1741     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1742     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1743   }
1744   else if (a3DViewer.IsNull())
1745   {
1746     toCreateViewer = Standard_True;
1747     a3DViewer = new V3d_Viewer(aGraphicDriver);
1748     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1749     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1750                                            ViewerTest_DefaultBackground.GradientColor2,
1751                                            ViewerTest_DefaultBackground.FillMethod);
1752   }
1753
1754   // AIS context setup
1755   if (ViewerTest::GetAISContext().IsNull() ||
1756       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1757   {
1758     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1759     ViewerTest::SetAISContext (aContext);
1760     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1761   }
1762   else
1763   {
1764     ViewerTest::ResetEventManager();
1765   }
1766
1767   // Create window
1768 #if defined(_WIN32)
1769   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1770                                     Handle(WNT_WClass)::DownCast (WClass()),
1771                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1772                                     aPxLeft, aPxTop,
1773                                     aPxWidth, aPxHeight,
1774                                     Quantity_NOC_BLACK);
1775 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1776   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1777                                      aPxLeft, aPxTop,
1778                                      aPxWidth, aPxHeight);
1779   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1780 #else
1781   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1782                                   aTitle.ToCString(),
1783                                   aPxLeft, aPxTop,
1784                                   aPxWidth, aPxHeight);
1785 #endif
1786   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1787
1788   // View setup
1789   Handle(V3d_View) aView;
1790   if (!theViewToClone.IsNull())
1791   {
1792     aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1793   }
1794   else
1795   {
1796     aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1797   }
1798
1799   aView->SetWindow (VT_GetWindow());
1800   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1801
1802   ViewerTest::CurrentView(aView);
1803   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1804
1805   // Setup for X11 or NT
1806   OSWindowSetup();
1807
1808   // Set parameters for V3d_View and V3d_Viewer
1809   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1810   aV3dView->SetComputedMode(Standard_False);
1811
1812   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1813   if (toCreateViewer)
1814   {
1815     a3DViewer->SetDefaultLights();
1816     a3DViewer->SetLightOn();
1817   }
1818
1819 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1820   if (isNewDriver)
1821   {
1822     ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1823     Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1824   }
1825 #endif
1826
1827   VT_GetWindow()->Map();
1828
1829   // Set the handle of created view in the event manager
1830   ViewerTest::ResetEventManager();
1831
1832   ViewerTest::CurrentView()->Redraw();
1833
1834   aView.Nullify();
1835   a3DViewer.Nullify();
1836
1837   return aViewNames.GetViewName();
1838 }
1839
1840 //==============================================================================
1841 //function : RedrawAllViews
1842 //purpose  : Redraw all created views
1843 //==============================================================================
1844 void ViewerTest::RedrawAllViews()
1845 {
1846   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
1847   for (; aViewIt.More(); aViewIt.Next())
1848   {
1849     const Handle(V3d_View)& aView = aViewIt.Key2();
1850     aView->Redraw();
1851   }
1852 }
1853
1854 //==============================================================================
1855 //function : Vinit
1856 //purpose  : Create the window viewer and initialize all the global variable
1857 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
1858 //==============================================================================
1859
1860 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1861 {
1862   TCollection_AsciiString aViewName, aDisplayName;
1863   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
1864   Handle(V3d_View) aCopyFrom;
1865   TCollection_AsciiString aName, aValue;
1866   int is2dMode = -1;
1867   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
1868   {
1869     const TCollection_AsciiString anArg = theArgVec[anArgIt];
1870     TCollection_AsciiString anArgCase = anArg;
1871     anArgCase.LowerCase();
1872     if (anArgIt + 1 < theArgsNb
1873      && anArgCase == "-name")
1874     {
1875       aViewName = theArgVec[++anArgIt];
1876     }
1877     else if (anArgIt + 1 < theArgsNb
1878           && (anArgCase == "-left"
1879            || anArgCase == "-l"))
1880     {
1881       aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
1882     }
1883     else if (anArgIt + 1 < theArgsNb
1884           && (anArgCase == "-top"
1885            || anArgCase == "-t"))
1886     {
1887       aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
1888     }
1889     else if (anArgIt + 1 < theArgsNb
1890           && (anArgCase == "-width"
1891            || anArgCase == "-w"))
1892     {
1893       aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
1894     }
1895     else if (anArgIt + 1 < theArgsNb
1896           && (anArgCase == "-height"
1897            || anArgCase == "-h"))
1898     {
1899       aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
1900     }
1901     else if (anArgCase == "-exitonclose")
1902     {
1903       ViewerTest_EventManager::ToExitOnCloseView() = true;
1904       if (anArgIt + 1 < theArgsNb
1905        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
1906       {
1907         ++anArgIt;
1908       }
1909     }
1910     else if (anArgCase == "-closeonescape"
1911           || anArgCase == "-closeonesc")
1912     {
1913       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
1914       if (anArgIt + 1 < theArgsNb
1915        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
1916       {
1917         ++anArgIt;
1918       }
1919     }
1920     else if (anArgCase == "-2d_mode"
1921           || anArgCase == "-2dmode"
1922           || anArgCase == "-2d")
1923     {
1924       bool toEnable = true;
1925       if (anArgIt + 1 < theArgsNb
1926        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
1927       {
1928         ++anArgIt;
1929       }
1930       is2dMode = toEnable ? 1 : 0;
1931     }
1932     else if (anArgIt + 1 < theArgsNb
1933           && (anArgCase == "-disp"
1934            || anArgCase == "-display"))
1935     {
1936       aDisplayName = theArgVec[++anArgIt];
1937     }
1938     else if (!ViewerTest::CurrentView().IsNull()
1939           &&  aCopyFrom.IsNull()
1940           && (anArgCase == "-copy"
1941            || anArgCase == "-clone"
1942            || anArgCase == "-cloneactive"
1943            || anArgCase == "-cloneactiveview"))
1944     {
1945       aCopyFrom = ViewerTest::CurrentView();
1946     }
1947     // old syntax
1948     else if (ViewerTest::SplitParameter (anArg, aName, aValue))
1949     {
1950       aName.LowerCase();
1951       if (aName == "name")
1952       {
1953         aViewName = aValue;
1954       }
1955       else if (aName == "l"
1956             || aName == "left")
1957       {
1958         aPxLeft = aValue.IntegerValue();
1959       }
1960       else if (aName == "t"
1961             || aName == "top")
1962       {
1963         aPxTop = aValue.IntegerValue();
1964       }
1965       else if (aName == "disp"
1966             || aName == "display")
1967       {
1968         aDisplayName = aValue;
1969       }
1970       else if (aName == "w"
1971             || aName == "width")
1972       {
1973         aPxWidth = aValue.IntegerValue();
1974       }
1975       else if (aName == "h"
1976             || aName == "height")
1977       {
1978         aPxHeight = aValue.IntegerValue();
1979       }
1980       else
1981       {
1982         std::cout << "Syntax error: unknown argument " << anArg << ".\n";
1983         return 1;
1984       }
1985     }
1986     else if (aViewName.IsEmpty())
1987     {
1988       aViewName = anArg;
1989     }
1990     else
1991     {
1992       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
1993       return 1;
1994     }
1995   }
1996
1997 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
1998   if (!aDisplayName.IsEmpty())
1999   {
2000     aDisplayName.Clear();
2001     std::cout << "Warning: display parameter will be ignored.\n";
2002   }
2003 #endif
2004
2005   ViewerTest_Names aViewNames (aViewName);
2006   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2007   {
2008     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2009     theDi.Eval (aCommand.ToCString());
2010     if (is2dMode != -1)
2011     {
2012       ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2013     }
2014     return 0;
2015   }
2016
2017   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2018                                                             aViewName, aDisplayName, aCopyFrom);
2019   if (is2dMode != -1)
2020   {
2021     ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2022   }
2023   theDi << aViewId;
2024   return 0;
2025 }
2026
2027 //! Parse HLR algo type.
2028 static Standard_Boolean parseHlrAlgoType (const char* theName,
2029                                           Prs3d_TypeOfHLR& theType)
2030 {
2031   TCollection_AsciiString aName (theName);
2032   aName.LowerCase();
2033   if (aName == "polyalgo")
2034   {
2035     theType = Prs3d_TOH_PolyAlgo;
2036   }
2037   else if (aName == "algo")
2038   {
2039     theType = Prs3d_TOH_Algo;
2040   }
2041   else
2042   {
2043     return Standard_False;
2044   }
2045   return Standard_True;
2046 }
2047
2048 //==============================================================================
2049 //function : VHLR
2050 //purpose  : hidden lines removal algorithm
2051 //==============================================================================
2052
2053 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2054 {
2055   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2056   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2057   if (aView.IsNull())
2058   {
2059     std::cerr << "Error: No opened viewer!\n";
2060     return 1;
2061   }
2062
2063   Standard_Boolean hasHlrOnArg = Standard_False;
2064   Standard_Boolean hasShowHiddenArg = Standard_False;
2065   Standard_Boolean isHLROn = Standard_False;
2066   Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2067   Prs3d_TypeOfHLR  aTypeOfHLR = Prs3d_TOH_NotSet;
2068   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2069   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2070   {
2071     TCollection_AsciiString anArg (argv[anArgIter]);
2072     anArg.LowerCase();
2073     if (anUpdateTool.parseRedrawMode (anArg))
2074     {
2075       continue;
2076     }
2077     else if (anArg == "-showhidden"
2078           && anArgIter + 1 < argc
2079           && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2080     {
2081       ++anArgIter;
2082       hasShowHiddenArg = Standard_True;
2083       continue;
2084     }
2085     else if ((anArg == "-type"
2086            || anArg == "-algo"
2087            || anArg == "-algotype")
2088           && anArgIter + 1 < argc
2089           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2090     {
2091       ++anArgIter;
2092       continue;
2093     }
2094     else if (!hasHlrOnArg
2095           && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2096     {
2097       hasHlrOnArg = Standard_True;
2098       continue;
2099     }
2100     // old syntax
2101     else if (!hasShowHiddenArg
2102           && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2103     {
2104       hasShowHiddenArg = Standard_True;
2105       continue;
2106     }
2107     else
2108     {
2109       std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2110       return 1;
2111     }
2112   }
2113   if (!hasHlrOnArg)
2114   {
2115     di << "HLR:        " << aView->ComputedMode() << "\n";
2116     di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2117     di << "HlrAlgo:    ";
2118     switch (aCtx->DefaultDrawer()->TypeOfHLR())
2119     {
2120       case Prs3d_TOH_NotSet:   di << "NotSet\n";   break;
2121       case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2122       case Prs3d_TOH_Algo:     di << "Algo\n";     break;
2123     }
2124     anUpdateTool.Invalidate();
2125     return 0;
2126   }
2127
2128   Standard_Boolean toRecompute = Standard_False;
2129   if (aTypeOfHLR != Prs3d_TOH_NotSet
2130    && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2131   {
2132     toRecompute = Standard_True;
2133     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2134   }
2135   if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2136   {
2137     toRecompute = Standard_True;
2138     if (toShowHidden)
2139     {
2140       aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2141     }
2142     else
2143     {
2144       aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2145     }
2146   }
2147
2148   // redisplay shapes
2149   if (aView->ComputedMode() && isHLROn && toRecompute)
2150   {
2151     AIS_ListOfInteractive aListOfShapes;
2152     aCtx->DisplayedObjects (aListOfShapes);
2153     for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2154     {
2155       if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2156       {
2157         aCtx->Redisplay (aShape, Standard_False);
2158       }
2159     }
2160   }
2161
2162   aView->SetComputedMode (isHLROn);
2163   return 0;
2164 }
2165
2166 //==============================================================================
2167 //function : VHLRType
2168 //purpose  : change type of using HLR algorithm
2169 //==============================================================================
2170
2171 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2172 {
2173   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2174   const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2175   if (aView.IsNull())
2176   {
2177     std::cerr << "Error: No opened viewer!\n";
2178     return 1;
2179   }
2180
2181   Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2182   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2183   AIS_ListOfInteractive aListOfShapes;
2184   for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2185   {
2186     TCollection_AsciiString anArg (argv[anArgIter]);
2187     anArg.LowerCase();
2188     if (anUpdateTool.parseRedrawMode (anArg))
2189     {
2190       continue;
2191     }
2192     else if ((anArg == "-type"
2193            || anArg == "-algo"
2194            || anArg == "-algotype")
2195           && anArgIter + 1 < argc
2196           && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2197     {
2198       ++anArgIter;
2199       continue;
2200     }
2201     // old syntax
2202     else if (aTypeOfHLR == Prs3d_TOH_NotSet
2203           && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2204     {
2205       continue;
2206     }
2207     else
2208     {
2209       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2210       TCollection_AsciiString aName (argv[anArgIter]);
2211       if (!aMap.IsBound2 (aName))
2212       {
2213         std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2214         return 1;
2215       }
2216
2217       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2218       if (aShape.IsNull())
2219       {
2220         std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2221         return 1;
2222       }
2223       aListOfShapes.Append (aShape);
2224       continue;
2225     }
2226   }
2227   if (aTypeOfHLR == Prs3d_TOH_NotSet)
2228   {
2229     std::cout << "Syntax error: wrong number of arguments!\n";
2230     return 1;
2231   }
2232
2233   const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2234   if (isGlobal)
2235   {
2236     aCtx->DisplayedObjects (aListOfShapes);
2237     aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2238   }
2239
2240   for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2241   {
2242     Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2243     if (aShape.IsNull())
2244     {
2245       continue;
2246     }
2247
2248     const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2249                             && aView->ComputedMode();
2250     if (!isGlobal
2251      || aShape->TypeOfHLR() != aTypeOfHLR)
2252     {
2253       aShape->SetTypeOfHLR (aTypeOfHLR);
2254     }
2255     if (toUpdateShape)
2256     {
2257       aCtx->Redisplay (aShape, Standard_False);
2258     }
2259   }
2260   return 0;
2261 }
2262
2263 //==============================================================================
2264 //function : FindViewIdByWindowHandle
2265 //purpose  : Find theView Id in the map of views by window handle
2266 //==============================================================================
2267 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2268 TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
2269 {
2270   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2271        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2272   {
2273     Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
2274     if (aWindowHandle == theWindowHandle)
2275       return anIter.Key1();
2276   }
2277   return TCollection_AsciiString("");
2278 }
2279 #endif
2280
2281 //! Make the view active
2282 void ActivateView (const TCollection_AsciiString& theViewName,
2283                    Standard_Boolean theToUpdate = Standard_True)
2284 {
2285   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2286   if (aView.IsNull())
2287   {
2288     return;
2289   }
2290
2291   Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2292   if (!anAISContext.IsNull())
2293   {
2294     if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
2295     {
2296       aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
2297     }
2298
2299     ViewerTest::CurrentView (aView);
2300     ViewerTest::SetAISContext (anAISContext);
2301     aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
2302 #if defined(_WIN32)
2303     VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2304 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2305     VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2306 #else
2307     VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2308 #endif
2309     SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2310     if (theToUpdate)
2311     {
2312       ViewerTest::CurrentView()->Redraw();
2313     }
2314   }
2315 }
2316
2317 //==============================================================================
2318 //function : RemoveView
2319 //purpose  :
2320 //==============================================================================
2321 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2322                              const Standard_Boolean  theToRemoveContext)
2323 {
2324   if (!ViewerTest_myViews.IsBound2 (theView))
2325   {
2326     return;
2327   }
2328
2329   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2330   RemoveView (aViewName, theToRemoveContext);
2331 }
2332
2333 //==============================================================================
2334 //function : RemoveView
2335 //purpose  : Close and remove view from display, clear maps if neccessary
2336 //==============================================================================
2337 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2338 {
2339   if (!ViewerTest_myViews.IsBound1(theViewName))
2340   {
2341     cout << "Wrong view name\n";
2342     return;
2343   }
2344
2345   // Activate another view if it's active now
2346   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2347   {
2348     if (ViewerTest_myViews.Extent() > 1)
2349     {
2350       TCollection_AsciiString aNewViewName;
2351       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2352            anIter.More(); anIter.Next())
2353       {
2354         if (anIter.Key1() != theViewName)
2355         {
2356           aNewViewName = anIter.Key1();
2357           break;
2358         }
2359       }
2360       ActivateView (aNewViewName);
2361     }
2362     else
2363     {
2364       VT_GetWindow().Nullify();
2365       ViewerTest::CurrentView (Handle(V3d_View)());
2366       if (isContextRemoved)
2367       {
2368         Handle(AIS_InteractiveContext) anEmptyContext;
2369         ViewerTest::SetAISContext(anEmptyContext);
2370       }
2371     }
2372   }
2373
2374   // Delete view
2375   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2376   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2377   ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2378   aRedrawer.Stop (aView->Window());
2379
2380   // Remove view resources
2381   ViewerTest_myViews.UnBind1(theViewName);
2382   aView->Window()->Unmap();
2383   aView->Remove();
2384
2385 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2386   XFlush (GetDisplayConnection()->GetDisplay());
2387 #endif
2388
2389   // Keep context opened only if the closed view is last to avoid
2390   // unused empty contexts
2391   if (!aCurrentContext.IsNull())
2392   {
2393     // Check if there are more difined views in the viewer
2394     aCurrentContext->CurrentViewer()->InitDefinedViews();
2395     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2396     {
2397       // Remove driver if there is no viewers that use it
2398       Standard_Boolean isRemoveDriver = Standard_True;
2399       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2400           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2401       {
2402         if (aCurrentContext != anIter.Key2() &&
2403           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2404         {
2405           isRemoveDriver = Standard_False;
2406           break;
2407         }
2408       }
2409
2410       aCurrentContext->RemoveAll (Standard_False);
2411       if(isRemoveDriver)
2412       {
2413         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2414       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2415         Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2416       #endif
2417       }
2418
2419       ViewerTest_myContexts.UnBind2(aCurrentContext);
2420     }
2421   }
2422   cout << "3D View - " << theViewName << " was deleted.\n";
2423   if (ViewerTest_EventManager::ToExitOnCloseView())
2424   {
2425     Draw_Interprete ("exit");
2426   }
2427 }
2428
2429 //==============================================================================
2430 //function : VClose
2431 //purpose  : Remove the view defined by its name
2432 //==============================================================================
2433
2434 static int VClose (Draw_Interpretor& /*theDi*/,
2435                    Standard_Integer  theArgsNb,
2436                    const char**      theArgVec)
2437 {
2438   NCollection_List<TCollection_AsciiString> aViewList;
2439   if (theArgsNb > 1)
2440   {
2441     TCollection_AsciiString anArg (theArgVec[1]);
2442     anArg.UpperCase();
2443     if (anArg.IsEqual ("ALL")
2444      || anArg.IsEqual ("*"))
2445     {
2446       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2447            anIter.More(); anIter.Next())
2448       {
2449         aViewList.Append (anIter.Key1());
2450       }
2451       if (aViewList.IsEmpty())
2452       {
2453         std::cout << "No view to close\n";
2454         return 0;
2455       }
2456     }
2457     else
2458     {
2459       ViewerTest_Names aViewName (theArgVec[1]);
2460       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2461       {
2462         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2463         return 1;
2464       }
2465       aViewList.Append (aViewName.GetViewName());
2466     }
2467   }
2468   else
2469   {
2470     // close active view
2471     if (ViewerTest::CurrentView().IsNull())
2472     {
2473       std::cerr << "No active view!\n";
2474       return 1;
2475     }
2476     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2477   }
2478
2479   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2480   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2481        anIter.More(); anIter.Next())
2482   {
2483     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2484   }
2485
2486   return 0;
2487 }
2488
2489 //==============================================================================
2490 //function : VActivate
2491 //purpose  : Activate the view defined by its ID
2492 //==============================================================================
2493
2494 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2495 {
2496   if (theArgsNb == 1)
2497   {
2498     theDi.Eval("vviewlist");
2499     return 0;
2500   }
2501
2502   TCollection_AsciiString aNameString;
2503   Standard_Boolean toUpdate = Standard_True;
2504   Standard_Boolean toActivate = Standard_True;
2505   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2506   {
2507     TCollection_AsciiString anArg (theArgVec[anArgIter]);
2508     anArg.LowerCase();
2509     if (toUpdate
2510      && anArg == "-noupdate")
2511     {
2512       toUpdate = Standard_False;
2513     }
2514     else if (toActivate
2515           && aNameString.IsEmpty()
2516           && anArg == "none")
2517     {
2518       ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2519       VT_GetWindow().Nullify();
2520       ViewerTest::CurrentView (Handle(V3d_View)());
2521       ViewerTest::ResetEventManager();
2522       theDi << theArgVec[0] << ": all views are inactive\n";
2523       toActivate = Standard_False;
2524     }
2525     else if (toActivate
2526           && aNameString.IsEmpty())
2527     {
2528       aNameString = theArgVec[anArgIter];
2529     }
2530     else
2531     {
2532       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2533       return 1;
2534     }
2535   }
2536
2537   if (!toActivate)
2538   {
2539     return 0;
2540   }
2541   else if (aNameString.IsEmpty())
2542   {
2543     std::cout << "Syntax error: wrong number of arguments\n";
2544     return 1;
2545   }
2546
2547   // Check if this view exists in the viewer with the driver
2548   ViewerTest_Names aViewNames (aNameString);
2549   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2550   {
2551     theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2552     return 1;
2553   }
2554
2555   // Check if it is active already
2556   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2557   {
2558     theDi << theArgVec[0] << ": the view is active already\n";
2559     return 0;
2560   }
2561
2562   ActivateView (aViewNames.GetViewName(), toUpdate);
2563   return 0;
2564 }
2565
2566 //==============================================================================
2567 //function : VViewList
2568 //purpose  : Print current list of views per viewer and graphic driver ID
2569 //           shared between viewers
2570 //==============================================================================
2571
2572 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2573 {
2574   if (theArgsNb > 2)
2575   {
2576     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2577           << "Usage: " << theArgVec[0] << " name";
2578     return 1;
2579   }
2580   if (ViewerTest_myContexts.Size() < 1)
2581     return 0;
2582
2583   Standard_Boolean isTreeView =
2584     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2585
2586   if (isTreeView)
2587   {
2588     theDi << theArgVec[0] <<":\n";
2589   }
2590
2591   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2592        aDriverIter.More(); aDriverIter.Next())
2593   {
2594     if (isTreeView)
2595       theDi << aDriverIter.Key1() << ":\n";
2596
2597     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2598       aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2599     {
2600       if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2601       {
2602         if (isTreeView)
2603         {
2604           TCollection_AsciiString aContextName(aContextIter.Key1());
2605           theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2606         }
2607
2608         for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2609              aViewIter.More(); aViewIter.Next())
2610         {
2611           if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2612           {
2613             TCollection_AsciiString aViewName(aViewIter.Key1());
2614             if (isTreeView)
2615             {
2616               if (aViewIter.Value() == ViewerTest::CurrentView())
2617                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2618               else
2619                 theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2620             }
2621             else
2622             {
2623               theDi << aViewName << " ";
2624             }
2625           }
2626         }
2627       }
2628     }
2629   }
2630   return 0;
2631 }
2632
2633 //==============================================================================
2634 //function : GetMousePosition
2635 //purpose  :
2636 //==============================================================================
2637 void ViewerTest::GetMousePosition (Standard_Integer& theX,
2638                                    Standard_Integer& theY)
2639 {
2640   if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
2641   {
2642     theX = aViewCtrl->LastMousePosition().x();
2643     theY = aViewCtrl->LastMousePosition().y();
2644   }
2645 }
2646
2647 //==============================================================================
2648 //function : VViewProj
2649 //purpose  : Switch view projection
2650 //==============================================================================
2651 static int VViewProj (Draw_Interpretor& ,
2652                       Standard_Integer theNbArgs,
2653                       const char** theArgVec)
2654 {
2655   static Standard_Boolean isYup = Standard_False;
2656   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2657   if (aView.IsNull())
2658   {
2659     std::cout << "Error: no active view\n";
2660     return 1;
2661   }
2662
2663   TCollection_AsciiString aCmdName (theArgVec[0]);
2664   Standard_Boolean isGeneralCmd = Standard_False;
2665   if (aCmdName == "vfront")
2666   {
2667     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2668   }
2669   else if (aCmdName == "vback")
2670   {
2671     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2672   }
2673   else if (aCmdName == "vtop")
2674   {
2675     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2676   }
2677   else if (aCmdName == "vbottom")
2678   {
2679     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2680   }
2681   else if (aCmdName == "vleft")
2682   {
2683     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2684   }
2685   else if (aCmdName == "vright")
2686   {
2687     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2688   }
2689   else if (aCmdName == "vaxo")
2690   {
2691     aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2692   }
2693   else
2694   {
2695     isGeneralCmd = Standard_True;
2696     for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2697     {
2698       TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2699       anArgCase.LowerCase();
2700       if (anArgCase == "-zup")
2701       {
2702         isYup = Standard_False;
2703       }
2704       else if (anArgCase == "-yup")
2705       {
2706         isYup = Standard_True;
2707       }
2708       else if (anArgCase == "-front"
2709             || anArgCase == "front"
2710             || anArgCase == "-f"
2711             || anArgCase == "f")
2712       {
2713         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2714       }
2715       else if (anArgCase == "-back"
2716             || anArgCase == "back"
2717             || anArgCase == "-b"
2718             || anArgCase == "b")
2719       {
2720         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2721       }
2722       else if (anArgCase == "-top"
2723             || anArgCase == "top"
2724             || anArgCase == "-t"
2725             || anArgCase == "t")
2726       {
2727         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2728       }
2729       else if (anArgCase == "-bottom"
2730             || anArgCase == "bottom"
2731             || anArgCase == "-bot"
2732             || anArgCase == "bot"
2733             || anArgCase == "-b"
2734             || anArgCase == "b")
2735       {
2736         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2737       }
2738       else if (anArgCase == "-left"
2739             || anArgCase == "left"
2740             || anArgCase == "-l"
2741             || anArgCase == "l")
2742       {
2743         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2744       }
2745       else if (anArgCase == "-right"
2746             || anArgCase == "right"
2747             || anArgCase == "-r"
2748             || anArgCase == "r")
2749       {
2750         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2751       }
2752       else if (anArgCase == "-axoleft"
2753             || anArgCase == "-leftaxo"
2754             || anArgCase == "axoleft"
2755             || anArgCase == "leftaxo")
2756       {
2757         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2758       }
2759       else if (anArgCase == "-axo"
2760             || anArgCase == "axo"
2761             || anArgCase == "-a"
2762             || anArgCase == "a"
2763             || anArgCase == "-axoright"
2764             || anArgCase == "-rightaxo"
2765             || anArgCase == "axoright"
2766             || anArgCase == "rightaxo")
2767       {
2768         aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2769       }
2770       else if (anArgCase == "+x")
2771       {
2772         aView->SetProj (V3d_Xpos, isYup);
2773       }
2774       else if (anArgCase == "-x")
2775       {
2776         aView->SetProj (V3d_Xneg, isYup);
2777       }
2778       else if (anArgCase == "+y")
2779       {
2780         aView->SetProj (V3d_Ypos, isYup);
2781       }
2782       else if (anArgCase == "-y")
2783       {
2784         aView->SetProj (V3d_Yneg, isYup);
2785       }
2786       else if (anArgCase == "+z")
2787       {
2788         aView->SetProj (V3d_Zpos, isYup);
2789       }
2790       else if (anArgCase == "-z")
2791       {
2792         aView->SetProj (V3d_Zneg, isYup);
2793       }
2794       else if (anArgCase == "+x+y+z")
2795       {
2796         aView->SetProj (V3d_XposYposZpos, isYup);
2797       }
2798       else if (anArgCase == "+x+y-z")
2799       {
2800         aView->SetProj (V3d_XposYposZneg, isYup);
2801       }
2802       else if (anArgCase == "+x-y+z")
2803       {
2804         aView->SetProj (V3d_XposYnegZpos, isYup);
2805       }
2806       else if (anArgCase == "+x-y-z")
2807       {
2808         aView->SetProj (V3d_XposYnegZneg, isYup);
2809       }
2810       else if (anArgCase == "-x+y+z")
2811       {
2812         aView->SetProj (V3d_XnegYposZpos, isYup);
2813       }
2814       else if (anArgCase == "-x+y-z")
2815       {
2816         aView->SetProj (V3d_XnegYposZneg, isYup);
2817       }
2818       else if (anArgCase == "-x-y+z")
2819       {
2820         aView->SetProj (V3d_XnegYnegZpos, isYup);
2821       }
2822       else if (anArgCase == "-x-y-z")
2823       {
2824         aView->SetProj (V3d_XnegYnegZneg, isYup);
2825       }
2826       else if (anArgCase == "+x+y")
2827       {
2828         aView->SetProj (V3d_XposYpos, isYup);
2829       }
2830       else if (anArgCase == "+x-y")
2831       {
2832         aView->SetProj (V3d_XposYneg, isYup);
2833       }
2834       else if (anArgCase == "-x+y")
2835       {
2836         aView->SetProj (V3d_XnegYpos, isYup);
2837       }
2838       else if (anArgCase == "-x-y")
2839       {
2840         aView->SetProj (V3d_XnegYneg, isYup);
2841       }
2842       else if (anArgCase == "+x+z")
2843       {
2844         aView->SetProj (V3d_XposZpos, isYup);
2845       }
2846       else if (anArgCase == "+x-z")
2847       {
2848         aView->SetProj (V3d_XposZneg, isYup);
2849       }
2850       else if (anArgCase == "-x+z")
2851       {
2852         aView->SetProj (V3d_XnegZpos, isYup);
2853       }
2854       else if (anArgCase == "-x-z")
2855       {
2856         aView->SetProj (V3d_XnegZneg, isYup);
2857       }
2858       else if (anArgCase == "+y+z")
2859       {
2860         aView->SetProj (V3d_YposZpos, isYup);
2861       }
2862       else if (anArgCase == "+y-z")
2863       {
2864         aView->SetProj (V3d_YposZneg, isYup);
2865       }
2866       else if (anArgCase == "-y+z")
2867       {
2868         aView->SetProj (V3d_YnegZpos, isYup);
2869       }
2870       else if (anArgCase == "-y-z")
2871       {
2872         aView->SetProj (V3d_YnegZneg, isYup);
2873       }
2874       else if (anArgIter + 1 < theNbArgs
2875             && anArgCase == "-frame"
2876             && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
2877       {
2878         TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
2879         aFrameDef.LowerCase();
2880         gp_Dir aRight, anUp;
2881         if (aFrameDef.Value (2) == aFrameDef.Value (4))
2882         {
2883           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2884           return 1;
2885         }
2886
2887         if (aFrameDef.Value (2) == 'x')
2888         {
2889           aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
2890         }
2891         else if (aFrameDef.Value (2) == 'y')
2892         {
2893           aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
2894         }
2895         else if (aFrameDef.Value (2) == 'z')
2896         {
2897           aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
2898         }
2899         else
2900         {
2901           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2902           return 1;
2903         }
2904
2905         if (aFrameDef.Value (4) == 'x')
2906         {
2907           anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
2908         }
2909         else if (aFrameDef.Value (4) == 'y')
2910         {
2911           anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
2912         }
2913         else if (aFrameDef.Value (4) == 'z')
2914         {
2915           anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
2916         }
2917         else
2918         {
2919           std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2920           return 1;
2921         }
2922
2923         const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
2924         const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
2925         const gp_Dir aDir = anUp.Crossed (aRight);
2926         aCamera->SetCenter (gp_Pnt (0, 0, 0));
2927         aCamera->SetDirection (aDir);
2928         aCamera->SetUp (anUp);
2929         aCamera->OrthogonalizeUp();
2930
2931         aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
2932         aView->Update();
2933       }
2934       else
2935       {
2936         std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2937         return 1;
2938       }
2939     }
2940   }
2941
2942   if (!isGeneralCmd
2943     && theNbArgs != 1)
2944   {
2945     std::cout << "Syntax error: wrong number of arguments\n";
2946     return 1;
2947   }
2948   return 0;
2949 }
2950
2951 //==============================================================================
2952 //function : VHelp
2953 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
2954 //Draw arg : No args
2955 //==============================================================================
2956
2957 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
2958 {
2959   di << "=========================\n";
2960   di << "F : FitAll\n";
2961   di << "T : TopView\n";
2962   di << "B : BottomView\n";
2963   di << "R : RightView\n";
2964   di << "L : LeftView\n";
2965   di << "A : AxonometricView\n";
2966   di << "D : ResetView\n";
2967
2968   di << "=========================\n";
2969   di << "S : Shading\n";
2970   di << "W : Wireframe\n";
2971   di << "H : HiddenLineRemoval\n";
2972   di << "U : Unset display mode\n";
2973   di << "Delete : Remove selection from viewer\n";
2974
2975   di << "=========================\n";
2976   di << "Selection mode \n";
2977   di << "0 : Shape\n";
2978   di << "1 : Vertex\n";
2979   di << "2 : Edge\n";
2980   di << "3 : Wire\n";
2981   di << "4 : Face\n";
2982   di << "5 : Shell\n";
2983   di << "6 : Solid\n";
2984   di << "7 : Compound\n";
2985
2986   di << "=========================\n";
2987   di << "< : Hilight next detected\n";
2988   di << "> : Hilight previous detected\n";
2989
2990   return 0;
2991 }
2992
2993 #ifdef _WIN32
2994
2995 static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
2996                                            UINT theMsg,
2997                                            WPARAM wParam,
2998                                            LPARAM lParam )
2999 {
3000   if (ViewerTest_myViews.IsEmpty())
3001   {
3002     return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3003   }
3004
3005   switch (theMsg)
3006   {
3007     case WM_CLOSE:
3008     {
3009       // Delete view from map of views
3010       ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3011       return 0;
3012     }
3013     case WM_ACTIVATE:
3014     {
3015       if (LOWORD(wParam) == WA_CLICKACTIVE
3016        || LOWORD(wParam) == WA_ACTIVE
3017        || ViewerTest::CurrentView().IsNull())
3018       {
3019         // Activate inactive window
3020         if (VT_GetWindow().IsNull()
3021          || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3022         {
3023           ActivateView (FindViewIdByWindowHandle (theWinHandle));
3024         }
3025       }
3026       break;
3027     }
3028     default:
3029     {
3030       return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3031     }
3032   }
3033   return 0;
3034 }
3035
3036 static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3037                                         UINT theMsg,
3038                                         WPARAM wParam,
3039                                         LPARAM lParam)
3040 {
3041   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3042   if (aView.IsNull())
3043   {
3044     return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3045   }
3046
3047   switch (theMsg)
3048   {
3049     case WM_PAINT:
3050     {
3051       PAINTSTRUCT aPaint;
3052       BeginPaint(theWinHandle, &aPaint);
3053       EndPaint  (theWinHandle, &aPaint);
3054       ViewerTest::CurrentEventManager()->ProcessExpose();
3055       break;
3056     }
3057     case WM_SIZE:
3058     {
3059       ViewerTest::CurrentEventManager()->ProcessConfigure();
3060       break;
3061     }
3062     case WM_MOVE:
3063     case WM_MOVING:
3064     case WM_SIZING:
3065     {
3066       switch (aView->RenderingParams().StereoMode)
3067       {
3068         case Graphic3d_StereoMode_RowInterlaced:
3069         case Graphic3d_StereoMode_ColumnInterlaced:
3070         case Graphic3d_StereoMode_ChessBoard:
3071         {
3072           // track window moves to reverse stereo pair
3073           aView->MustBeResized();
3074           aView->Update();
3075           break;
3076         }
3077         default:
3078           break;
3079       }
3080       break;
3081     }
3082     case WM_KEYUP:
3083     case WM_KEYDOWN:
3084     {
3085       const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3086       if (aVKey != Aspect_VKey_UNKNOWN)
3087       {
3088         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3089         if (theMsg == WM_KEYDOWN)
3090         {
3091           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3092         }
3093         else
3094         {
3095           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3096         }
3097         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3098       }
3099       break;
3100     }
3101     case WM_LBUTTONUP:
3102     case WM_MBUTTONUP:
3103     case WM_RBUTTONUP:
3104     case WM_LBUTTONDOWN:
3105     case WM_MBUTTONDOWN:
3106     case WM_RBUTTONDOWN:
3107     {
3108       const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3109       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3110       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3111       switch (theMsg)
3112       {
3113         case WM_LBUTTONUP:
3114         case WM_LBUTTONDOWN:
3115           aButton = Aspect_VKeyMouse_LeftButton;
3116           break;
3117         case WM_MBUTTONUP:
3118         case WM_MBUTTONDOWN:
3119           aButton = Aspect_VKeyMouse_MiddleButton;
3120           break;
3121         case WM_RBUTTONUP:
3122         case WM_RBUTTONDOWN:
3123           aButton = Aspect_VKeyMouse_RightButton;
3124           break;
3125       }
3126       if (theMsg == WM_LBUTTONDOWN
3127        || theMsg == WM_MBUTTONDOWN
3128        || theMsg == WM_RBUTTONDOWN)
3129       {
3130         if (aButton == Aspect_VKeyMouse_LeftButton)
3131         {
3132           TheIsAnimating = Standard_False;
3133         }
3134
3135         SetFocus  (theWinHandle);
3136         SetCapture(theWinHandle);
3137         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3138       }
3139       else
3140       {
3141         ReleaseCapture();
3142         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3143       }
3144       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3145       break;
3146     }
3147     case WM_MOUSEWHEEL:
3148     {
3149       const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3150       const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3151       const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3152       Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3153       POINT aCursorPnt = { aPos.x(), aPos.y() };
3154       if (ScreenToClient (theWinHandle, &aCursorPnt))
3155       {
3156         aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3157       }
3158
3159       ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3160       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3161       break;
3162     }
3163     case WM_MOUSEMOVE:
3164     {
3165       Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3166       Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3167       Aspect_VKeyFlags aFlags   = WNT_Window::MouseKeyFlagsFromEvent(wParam);
3168
3169       // don't make a slide-show from input events - fetch the actual mouse cursor position
3170       CURSORINFO aCursor;
3171       aCursor.cbSize = sizeof(aCursor);
3172       if (::GetCursorInfo (&aCursor) != FALSE)
3173       {
3174         POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3175         if (ScreenToClient (theWinHandle, &aCursorPnt))
3176         {
3177           // as we override mouse position, we need overriding also mouse state
3178           aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3179           aButtons = WNT_Window::MouseButtonsAsync();
3180           aFlags   = WNT_Window::MouseKeyFlagsAsync();
3181         }
3182       }
3183
3184       if (VT_GetWindow().IsNull()
3185       || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3186       {
3187         // mouse move events come also for inactive windows
3188         break;
3189       }
3190
3191       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3192       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
3193       break;
3194     }
3195     default:
3196     {
3197       return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3198     }
3199   }
3200   return 0L;
3201 }
3202
3203 //==============================================================================
3204 //function : ViewerMainLoop
3205 //purpose  : Get a Event on the view and dispatch it
3206 //==============================================================================
3207
3208 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3209 {
3210   Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
3211   if (aViewCtrl.IsNull()
3212    || theNbArgs < 4)
3213   {
3214     return 0;
3215   }
3216
3217   aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3218
3219   std::cout << "Start picking\n";
3220
3221   MSG aMsg;
3222   aMsg.wParam = 1;
3223   while (aViewCtrl->ToPickPoint())
3224   {
3225     // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3226     if (GetMessageW (&aMsg, NULL, 0, 0))
3227     {
3228       TranslateMessage (&aMsg);
3229       DispatchMessageW (&aMsg);
3230     }
3231   }
3232
3233   std::cout << "Picking done\n";
3234   return 0;
3235 }
3236
3237 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3238
3239 int min( int a, int b )
3240 {
3241   if( a<b )
3242     return a;
3243   else
3244     return b;
3245 }
3246
3247 int max( int a, int b )
3248 {
3249   if( a>b )
3250     return a;
3251   else
3252     return b;
3253 }
3254
3255 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3256 {
3257   static XEvent aReport;
3258   const Standard_Boolean toPick = theNbArgs > 0;
3259   if (theNbArgs > 0)
3260   {
3261     if (ViewerTest::CurrentEventManager().IsNull())
3262     {
3263       return 0;
3264     }
3265     ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3266   }
3267
3268   Display* aDisplay = GetDisplayConnection()->GetDisplay();
3269   XNextEvent (aDisplay, &aReport);
3270
3271   // Handle event for the chosen display connection
3272   switch (aReport.type)
3273   {
3274     case ClientMessage:
3275     {
3276       if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3277       {
3278         // Close the window
3279         ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3280         return toPick ? 0 : 1;
3281       }
3282       break;
3283     }
3284     case FocusIn:
3285     {
3286       // Activate inactive view
3287       Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3288       if (aWindow != aReport.xfocus.window)
3289       {
3290         ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3291       }
3292       break;
3293     }
3294     case Expose:
3295     {
3296       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3297       if (anXWindow == aReport.xexpose.window)
3298       {
3299         ViewerTest::CurrentEventManager()->ProcessExpose();
3300       }
3301
3302       // remove all the ExposureMask and process them at once
3303       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3304       {
3305         if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3306         {
3307           break;
3308         }
3309       }
3310
3311       break;
3312     }
3313     case ConfigureNotify:
3314     {
3315       // remove all the StructureNotifyMask and process them at once
3316       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3317       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3318       {
3319         if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3320         {
3321           break;
3322         }
3323       }
3324
3325       if (anXWindow == aReport.xconfigure.window)
3326       {
3327         ViewerTest::CurrentEventManager()->ProcessConfigure();
3328       }
3329       break;
3330     }
3331     case KeyPress:
3332     case KeyRelease:
3333     {
3334       XKeyEvent*   aKeyEvent = (XKeyEvent* )&aReport;
3335       const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
3336       const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
3337       if (aVKey != Aspect_VKey_UNKNOWN)
3338       {
3339         const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3340         if (aReport.type == KeyPress)
3341         {
3342           ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3343         }
3344         else
3345         {
3346           ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3347         }
3348         ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3349       }
3350       break;
3351     }
3352     case ButtonPress:
3353     case ButtonRelease:
3354     {
3355       const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
3356       Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3357       Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3358       if (aReport.xbutton.button == Button1)
3359       {
3360         aButton = Aspect_VKeyMouse_LeftButton;
3361       }
3362       if (aReport.xbutton.button == Button2)
3363       {
3364         aButton = Aspect_VKeyMouse_MiddleButton;
3365       }
3366       if (aReport.xbutton.button == Button3)
3367       {
3368         aButton = Aspect_VKeyMouse_RightButton;
3369       }
3370
3371       if (aReport.xbutton.state & ControlMask)
3372       {
3373         aFlags |= Aspect_VKeyFlags_CTRL;
3374       }
3375       if (aReport.xbutton.state & ShiftMask)
3376       {
3377         aFlags |= Aspect_VKeyFlags_SHIFT;
3378       }
3379       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3380       {
3381         aFlags |= Aspect_VKeyFlags_ALT;
3382       }
3383
3384       if (aReport.xbutton.button == Button4
3385        || aReport.xbutton.button == Button5)
3386       {
3387         if (aReport.type != ButtonPress)
3388         {
3389           break;
3390         }
3391
3392         const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
3393         ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3394       }
3395       else if (aReport.type == ButtonPress)
3396       {
3397         if (aButton == Aspect_VKeyMouse_LeftButton)
3398         {
3399           TheIsAnimating = Standard_False;
3400         }
3401         ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3402       }
3403       else
3404       {
3405         ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3406       }
3407       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3408       break;
3409     }
3410     case MotionNotify:
3411     {
3412       Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3413       if (anXWindow != aReport.xmotion.window)
3414       {
3415         break;
3416       }
3417
3418       // remove all the ButtonMotionMask and process them at once
3419       for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3420       {
3421         if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3422         {
3423           break;
3424         }
3425       }
3426
3427       Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
3428       Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
3429       Aspect_VKeyFlags aFlags   = Aspect_VKeyFlags_NONE;
3430       if ((aReport.xmotion.state & Button1Mask) != 0)
3431       {
3432         aButtons |= Aspect_VKeyMouse_LeftButton;
3433       }
3434       else if ((aReport.xmotion.state & Button2Mask) != 0)
3435       {
3436         aButtons |= Aspect_VKeyMouse_MiddleButton;
3437       }
3438       else if ((aReport.xmotion.state & Button3Mask) != 0)
3439       {
3440         aButtons |= Aspect_VKeyMouse_RightButton;
3441       }
3442
3443       if (aReport.xmotion.state & ControlMask)
3444       {
3445         aFlags |= Aspect_VKeyFlags_CTRL;
3446       }
3447       if (aReport.xmotion.state & ShiftMask)
3448       {
3449         aFlags |= Aspect_VKeyFlags_SHIFT;
3450       }
3451       if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3452       {
3453         aFlags |= Aspect_VKeyFlags_ALT;
3454       }
3455
3456       ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3457       ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3458       break;
3459     }
3460   }
3461   return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
3462 }
3463
3464 //==============================================================================
3465 //function : VProcessEvents
3466 //purpose  : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3467 //==============================================================================
3468 static void VProcessEvents (ClientData theDispX, int)
3469 {
3470   Display* aDispX = (Display* )theDispX;
3471   Handle(Aspect_DisplayConnection) aDispConn;
3472   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3473        aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3474   {
3475     const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3476     if (aDispConnTmp->GetDisplay() == aDispX)
3477     {
3478       aDispConn = aDispConnTmp;
3479       break;
3480     }
3481   }
3482   if (aDispConn.IsNull())
3483   {
3484     std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3485     return;
3486   }
3487
3488   // process new events in queue
3489   SetDisplayConnection (aDispConn);
3490   int aNbRemain = 0;
3491   for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3492   {
3493     const int anEventResult = ViewerMainLoop (0, NULL);
3494     if (anEventResult == 0)
3495     {
3496       return;
3497     }
3498
3499     aNbRemain = XPending (aDispX);
3500     if (++anEventIter >= aNbEventsMax
3501      || aNbRemain <= 0)
3502     {
3503       break;
3504     }
3505   }
3506
3507   // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3508   // it is possible that new events will arrive to queue before the end of this callback
3509   // so that either this callback should go into an infinite loop (blocking processing of other events)
3510   // or to keep unprocessed events till the next queue update (which can arrive not soon).
3511   // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3512   if (aNbRemain != 0)
3513   {
3514     XEvent aDummyEvent;
3515     memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3516     aDummyEvent.type = ClientMessage;
3517     aDummyEvent.xclient.format = 32;
3518     XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3519     XFlush (aDispX);
3520   }
3521
3522   if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3523   {
3524     SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3525   }
3526 }
3527 #endif
3528
3529 //==============================================================================
3530 //function : OSWindowSetup
3531 //purpose  : Setup for the X11 window to be able to cath the event
3532 //==============================================================================
3533
3534
3535 static void OSWindowSetup()
3536 {
3537 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
3538   // X11
3539
3540   Window  window   = VT_GetWindow()->XWindow();
3541   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
3542   Display *aDisplay = GetDisplayConnection()->GetDisplay();
3543   XSynchronize(aDisplay, 1);
3544
3545   // X11 : For keyboard on SUN
3546   XWMHints wmhints;
3547   wmhints.flags = InputHint;
3548   wmhints.input = 1;
3549
3550   XSetWMHints( aDisplay, window, &wmhints);
3551
3552   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask | KeyReleaseMask |
3553     ButtonPressMask | ButtonReleaseMask |
3554     StructureNotifyMask |
3555     PointerMotionMask |
3556     Button1MotionMask | Button2MotionMask |
3557     Button3MotionMask | FocusChangeMask
3558     );
3559   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3560   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3561
3562   XSynchronize(aDisplay, 0);
3563
3564 #else
3565   // _WIN32
3566 #endif
3567
3568 }
3569
3570 //==============================================================================
3571 //function : VFit
3572 //purpose  :
3573 //==============================================================================
3574
3575 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3576 {
3577   const Handle(V3d_View) aView = ViewerTest::CurrentView();
3578   if (aView.IsNull())
3579   {
3580     std::cout << "Error: no active viewer!\n";
3581     return 1;
3582   }
3583
3584   Standard_Boolean toFit = Standard_True;
3585   ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3586   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3587   {
3588     TCollection_AsciiString anArg (theArgv[anArgIter]);
3589     anArg.LowerCase();
3590     if (anUpdateTool.parseRedrawMode (anArg))
3591     {
3592       continue;
3593     }
3594     else if (anArg == "-selected")
3595     {
3596       ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3597       toFit = Standard_False;
3598     }
3599     else
3600     {
3601       std::cout << "Syntax error at '" << anArg << "'\n";
3602     }
3603   }
3604
3605   if (toFit)
3606   {
3607     aView->FitAll (0.01, Standard_False);
3608   }
3609   return 0;
3610 }
3611
3612 //=======================================================================
3613 //function : VFitArea
3614 //purpose  : Fit view to show area located between two points
3615 //         : given in world 2D or 3D coordinates.
3616 //=======================================================================
3617 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
3618 {
3619   Handle(V3d_View) aView = ViewerTest::CurrentView();
3620   if (aView.IsNull())
3621   {
3622     std::cerr << theArgVec[0] << "Error: No active view.\n";
3623     return 1;
3624   }
3625
3626   // Parse arguments.
3627   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3628   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3629
3630   if (theArgNb == 5)
3631   {
3632     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3633     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3634     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3635     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3636   }
3637   else if (theArgNb == 7)
3638   {
3639     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3640     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3641     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3642     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3643     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3644     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3645   }
3646   else
3647   {
3648     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3649     theDI.PrintHelp(theArgVec[0]);
3650     return 1;
3651   }
3652
3653   // Convert model coordinates to view space
3654   Handle(Graphic3d_Camera) aCamera = aView->Camera();
3655   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3656   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3657
3658   // Determine fit area
3659   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3660   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3661
3662   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3663
3664   if (aDiagonal < Precision::Confusion())
3665   {
3666     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3667     return 1;
3668   }
3669
3670   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3671   return 0;
3672 }
3673
3674 //==============================================================================
3675 //function : VZFit
3676 //purpose  : ZFitall, no DRAW arguments
3677 //Draw arg : No args
3678 //==============================================================================
3679 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3680 {
3681   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3682
3683   if (aCurrentView.IsNull())
3684   {
3685     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3686     return 1;
3687   }
3688
3689   if (theArgsNb == 1)
3690   {
3691     aCurrentView->ZFitAll();
3692     aCurrentView->Redraw();
3693     return 0;
3694   }
3695
3696   Standard_Real aScale = 1.0;
3697
3698   if (theArgsNb >= 2)
3699   {
3700     aScale = Draw::Atoi (theArgVec[1]);
3701   }
3702
3703   aCurrentView->ZFitAll (aScale);
3704   aCurrentView->Redraw();
3705
3706   return 0;
3707 }
3708
3709 //==============================================================================
3710 //function : VRepaint
3711 //purpose  :
3712 //==============================================================================
3713 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3714 {
3715   Handle(V3d_View) aView = ViewerTest::CurrentView();
3716   if (aView.IsNull())
3717   {
3718     std::cout << "Error: no active viewer!\n";
3719     return 1;
3720   }
3721
3722   Standard_Boolean isImmediateUpdate = Standard_False;
3723   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3724   {
3725     TCollection_AsciiString anArg (theArgVec[anArgIter]);
3726     anArg.LowerCase();
3727     if (anArg == "-immediate"
3728      || anArg == "-imm")
3729     {
3730       isImmediateUpdate = Standard_True;
3731       if (anArgIter + 1 < theArgNb
3732        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3733       {
3734         ++anArgIter;
3735       }
3736     }
3737     else if (anArg == "-continuous"
3738           || anArg == "-cont"
3739           || anArg == "-fps"
3740           || anArg == "-framerate")
3741     {
3742       Standard_Real aFps = -1.0;
3743       if (anArgIter + 1 < theArgNb
3744        && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3745       {
3746         aFps = Draw::Atof (theArgVec[++anArgIter]);
3747       }
3748
3749       ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3750       if (Abs (aFps) >= 1.0)
3751       {
3752         aRedrawer.Start (aView->Window(), aFps);
3753       }
3754       else
3755       {
3756         aRedrawer.Stop();
3757       }
3758     }
3759     else
3760     {
3761       std::cout << "Syntax error at '" << anArg << "'\n";
3762       return 1;
3763     }
3764   }
3765
3766   if (isImmediateUpdate)
3767   {
3768     aView->RedrawImmediate();
3769   }
3770   else
3771   {
3772     aView->Redraw();
3773   }
3774   return 0;
3775 }
3776
3777 //==============================================================================
3778 //function : VClear
3779 //purpose  : Remove all the object from the viewer
3780 //Draw arg : No args
3781 //==============================================================================
3782
3783 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3784 {
3785   Handle(V3d_View) V = ViewerTest::CurrentView();
3786   if(!V.IsNull())
3787     ViewerTest::Clear();
3788   return 0;
3789 }
3790
3791 //==============================================================================
3792 //function : VPick
3793 //purpose  :
3794 //==============================================================================
3795
3796 static int VPick (Draw_Interpretor& ,
3797                   Standard_Integer theNbArgs,
3798                   const char** theArgVec)
3799 {
3800   if (ViewerTest::CurrentView().IsNull())
3801   {
3802     return 1;
3803   }
3804
3805   if (theNbArgs < 4)
3806   {
3807     std::cout << "Syntax error: Invalid number of arguments\n";
3808     return 1;
3809   }
3810
3811   while (ViewerMainLoop (theNbArgs, theArgVec))
3812   {
3813     //
3814   }
3815
3816   return 0;
3817 }
3818
3819 namespace
3820 {
3821
3822   //! Changes the background
3823   //! @param theDrawInterpretor the interpreter of the Draw Harness application
3824   //! @param theNumberOfCommandLineArguments the number of passed command line arguments
3825   //! @param theCommandLineArguments the array of command line arguments
3826   //! @return TCL_OK if changing was successful, or TCL_ERROR otherwise
3827   static int vbackground (Draw_Interpretor&      theDrawInterpretor,
3828                           const Standard_Integer theNumberOfCommandLineArguments,
3829                           const char** const     theCommandLineArguments)
3830   {
3831     if (theNumberOfCommandLineArguments < 1)
3832     {
3833       return TCL_ERROR;
3834     }
3835     BackgroundChanger aBackgroundChanger;
3836     if (!aBackgroundChanger.ProcessCommandLine (theDrawInterpretor,
3837                                                 theNumberOfCommandLineArguments,
3838                                                 theCommandLineArguments))
3839     {
3840       theDrawInterpretor << "Wrong command arguments.\n"
3841                             "Type 'help "
3842                          << theCommandLineArguments[0] << "' for information about command options and its arguments.\n";
3843       return TCL_ERROR;
3844     }
3845     return TCL_OK;
3846   }
3847
3848 } // namespace
3849
3850 //==============================================================================
3851 //function : VScale
3852 //purpose  : View Scaling
3853 //==============================================================================
3854
3855 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3856 {
3857   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3858   if ( V3dView.IsNull() ) return 1;
3859
3860   if ( argc != 4 ) {
3861     di << argv[0] << "Invalid number of arguments\n";
3862     return 1;
3863   }
3864   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
3865   return 0;
3866 }
3867 //==============================================================================
3868 //function : VZBuffTrihedron
3869 //purpose  :
3870 //==============================================================================
3871
3872 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
3873                             Standard_Integer  theArgNb,
3874                             const char**      theArgVec)
3875 {
3876   Handle(V3d_View) aView = ViewerTest::CurrentView();
3877   if (aView.IsNull())
3878   {
3879     std::cout << "Error: no active viewer!\n";
3880     return 1;
3881   }
3882
3883   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
3884
3885   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
3886   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
3887   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
3888   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
3889   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
3890   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
3891   Standard_Real                 aScale        = 0.1;
3892   Standard_Real                 aSizeRatio    = 0.8;
3893   Standard_Real                 anArrowDiam   = 0.05;
3894   Standard_Integer              aNbFacets     = 12;
3895   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3896   {
3897     Standard_CString        anArg = theArgVec[anArgIter];
3898     TCollection_AsciiString aFlag (anArg);
3899     aFlag.LowerCase();
3900     if (anUpdateTool.parseRedrawMode (aFlag))
3901     {
3902       continue;
3903     }
3904     else if (aFlag == "-on")
3905     {
3906       continue;
3907     }
3908     else if (aFlag == "-off")
3909     {
3910       aView->TriedronErase();
3911       return 0;
3912     }
3913     else if (aFlag == "-pos"
3914           || aFlag == "-position"
3915           || aFlag == "-corner")
3916     {
3917       if (++anArgIter >= theArgNb)
3918       {
3919         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3920         return 1;
3921       }
3922
3923       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3924       aPosName.LowerCase();
3925       if (aPosName == "center")
3926       {
3927         aPosition = Aspect_TOTP_CENTER;
3928       }
3929       else if (aPosName == "left_lower"
3930             || aPosName == "lower_left"
3931             || aPosName == "leftlower"
3932             || aPosName == "lowerleft")
3933       {
3934         aPosition = Aspect_TOTP_LEFT_LOWER;
3935       }
3936       else if (aPosName == "left_upper"
3937             || aPosName == "upper_left"
3938             || aPosName == "leftupper"
3939             || aPosName == "upperleft")
3940       {
3941         aPosition = Aspect_TOTP_LEFT_UPPER;
3942       }
3943       else if (aPosName == "right_lower"
3944             || aPosName == "lower_right"
3945             || aPosName == "rightlower"
3946             || aPosName == "lowerright")
3947       {
3948         aPosition = Aspect_TOTP_RIGHT_LOWER;
3949       }
3950       else if (aPosName == "right_upper"
3951             || aPosName == "upper_right"
3952             || aPosName == "rightupper"
3953             || aPosName == "upperright")
3954       {
3955         aPosition = Aspect_TOTP_RIGHT_UPPER;
3956       }
3957       else
3958       {
3959         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3960         return 1;
3961       }
3962     }
3963     else if (aFlag == "-type")
3964     {
3965       if (++anArgIter >= theArgNb)
3966       {
3967         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3968         return 1;
3969       }
3970
3971       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3972       aTypeName.LowerCase();
3973       if (aTypeName == "wireframe"
3974        || aTypeName == "wire")
3975       {
3976         aVisType = V3d_WIREFRAME;
3977       }
3978       else if (aTypeName == "zbuffer"
3979             || aTypeName == "shaded")
3980       {
3981         aVisType = V3d_ZBUFFER;
3982       }
3983       else
3984       {
3985         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3986       }
3987     }
3988     else if (aFlag == "-scale")
3989     {
3990       if (++anArgIter >= theArgNb)
3991       {
3992         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3993         return 1;
3994       }
3995
3996       aScale = Draw::Atof (theArgVec[anArgIter]);
3997     }
3998     else if (aFlag == "-size"
3999           || aFlag == "-sizeratio")
4000     {
4001       if (++anArgIter >= theArgNb)
4002       {
4003         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4004         return 1;
4005       }
4006
4007       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
4008     }
4009     else if (aFlag == "-arrowdiam"
4010           || aFlag == "-arrowdiameter")
4011     {
4012       if (++anArgIter >= theArgNb)
4013       {
4014         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4015         return 1;
4016       }
4017
4018       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
4019     }
4020     else if (aFlag == "-nbfacets")
4021     {
4022       if (++anArgIter >= theArgNb)
4023       {
4024         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4025         return 1;
4026       }
4027
4028       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
4029     }
4030     else if (aFlag == "-colorlabel"
4031           || aFlag == "-colorlabels")
4032     {
4033       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4034                                                            theArgVec + anArgIter + 1,
4035                                                            aLabelsColor);
4036       if (aNbParsed == 0)
4037       {
4038         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4039         return 1;
4040       }
4041       anArgIter += aNbParsed;
4042     }
4043     else if (aFlag == "-colorarrowx")
4044     {
4045       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4046                                                            theArgVec + anArgIter + 1,
4047                                                            anArrowColorX);
4048       if (aNbParsed == 0)
4049       {
4050         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4051         return 1;
4052       }
4053       anArgIter += aNbParsed;
4054     }
4055     else if (aFlag == "-colorarrowy")
4056     {
4057       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4058                                                            theArgVec + anArgIter + 1,
4059                                                            anArrowColorY);
4060       if (aNbParsed == 0)
4061       {
4062         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4063         return 1;
4064       }
4065       anArgIter += aNbParsed;
4066     }
4067     else if (aFlag == "-colorarrowz")
4068     {
4069       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
4070                                                            theArgVec + anArgIter + 1,
4071                                                            anArrowColorZ);
4072       if (aNbParsed == 0)
4073       {
4074         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4075         return 1;
4076       }
4077       anArgIter += aNbParsed;
4078     }
4079     else
4080     {
4081       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4082       return 1;
4083     }
4084   }
4085
4086   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
4087                                aSizeRatio, anArrowDiam, aNbFacets);
4088   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
4089   aView->ZFitAll();
4090   return 0;
4091 }
4092
4093 //==============================================================================
4094 //function : VRotate
4095 //purpose  : Camera Rotating
4096 //==============================================================================
4097
4098 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
4099 {
4100   Handle(V3d_View) aView = ViewerTest::CurrentView();
4101   if (aView.IsNull())
4102   {
4103     std::cout << "No active view!\n";
4104     return 1;
4105   }
4106
4107   Standard_Boolean hasFlags = Standard_False;
4108   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
4109   {
4110     Standard_CString        anArg (theArgVec[anArgIter]);
4111     TCollection_AsciiString aFlag (anArg);
4112     aFlag.LowerCase();
4113     if (aFlag == "-mousestart"
4114      || aFlag == "-mousefrom")
4115     {
4116       hasFlags = Standard_True;
4117       if (anArgIter + 2 >= theArgNb)
4118       {
4119         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4120         return 1;
4121       }
4122
4123       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4124       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4125       aView->StartRotation (anX, anY);
4126     }
4127     else if (aFlag == "-mousemove")
4128     {
4129       hasFlags = Standard_True;
4130       if (anArgIter + 2 >= theArgNb)
4131       {
4132         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4133         return 1;
4134       }
4135
4136       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
4137       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
4138       aView->Rotation (anX, anY);
4139     }
4140     else if (theArgNb != 4
4141           && theArgNb != 7)
4142     {
4143       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
4144       return 1;
4145     }
4146   }
4147
4148   if (hasFlags)
4149   {
4150     return 0;
4151   }
4152   else if (theArgNb == 4)
4153   {
4154     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4155     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4156     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4157     aView->Rotate (anAX, anAY, anAZ);
4158     return 0;
4159   }
4160   else if (theArgNb == 7)
4161   {
4162     Standard_Real anAX = Draw::Atof (theArgVec[1]);
4163     Standard_Real anAY = Draw::Atof (theArgVec[2]);
4164     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
4165
4166     Standard_Real anX = Draw::Atof (theArgVec[4]);
4167     Standard_Real anY = Draw::Atof (theArgVec[5]);
4168     Standard_Real anZ = Draw::Atof (theArgVec[6]);
4169
4170     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
4171     return 0;
4172   }
4173
4174   std::cout << "Error: Invalid number of arguments\n";
4175   return 1;
4176 }
4177
4178 //==============================================================================
4179 //function : VZoom
4180 //purpose  : View zoom in / out (relative to current zoom)
4181 //==============================================================================
4182
4183 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4184   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4185   if ( V3dView.IsNull() ) {
4186     return 1;
4187   }
4188
4189   if ( argc == 2 ) {
4190     Standard_Real coef = Draw::Atof(argv[1]);
4191     if ( coef <= 0.0 ) {
4192       di << argv[1] << "Invalid value\n";
4193       return 1;
4194     }
4195     V3dView->SetZoom( Draw::Atof(argv[1]) );
4196     return 0;
4197   } else {
4198     di << argv[0] << " Invalid number of arguments\n";
4199     return 1;
4200   }
4201 }
4202
4203 //==============================================================================
4204 //function : VPan
4205 //purpose  : View panning (in pixels)
4206 //==============================================================================
4207
4208 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
4209   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
4210   if ( V3dView.IsNull() ) return 1;
4211
4212   if ( argc == 3 ) {
4213     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
4214     return 0;
4215   } else {
4216     di << argv[0] << " Invalid number of arguments\n";
4217     return 1;
4218   }
4219 }
4220
4221 //==============================================================================
4222 //function : VPlace
4223 //purpose  : Place the point (in pixels) at the center of the window
4224 //==============================================================================
4225 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
4226 {
4227   Handle(V3d_View) aView = ViewerTest::CurrentView();
4228   if (aView.IsNull())
4229   {
4230     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
4231     return 1;
4232   }
4233
4234   if (theArgNb != 3)
4235   {
4236     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
4237     return 1;
4238   }
4239
4240   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
4241
4242   return 0;
4243 }
4244
4245 static int VColorScale (Draw_Interpretor& theDI,
4246                         Standard_Integer  theArgNb,
4247                         const char**      theArgVec)
4248 {
4249   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
4250   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
4251   if (aContext.IsNull())
4252   {
4253     std::cout << "Error: no active view!\n";
4254     return 1;
4255   }
4256   if (theArgNb <= 1)
4257   {
4258     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
4259     return 1;
4260   }
4261
4262   Handle(AIS_ColorScale) aColorScale;
4263   if (GetMapOfAIS().IsBound2 (theArgVec[1]))
4264   {
4265     // find existing object
4266     aColorScale = Handle(AIS_ColorScale)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
4267     if (aColorScale.IsNull())
4268     {
4269       std::cout << "Error: object '" << theArgVec[1] << "'is already defined and is not a color scale!\n";
4270       return 1;
4271     }
4272   }
4273
4274   if (theArgNb <= 2)
4275   {
4276     if (aColorScale.IsNull())
4277     {
4278       std::cout << "Syntax error: colorscale with a given name does not exist.\n";
4279       return 1;
4280     }
4281
4282     theDI << "Color scale parameters for '"<< theArgVec[1] << "':\n"
4283           << "Min range: "            << aColorScale->GetMin() << "\n"
4284           << "Max range: "            << aColorScale->GetMax() << "\n"
4285           << "Number of intervals: "  << aColorScale->GetNumberOfIntervals() << "\n"
4286           << "Text height: "          << aColorScale->GetTextHeight() << "\n"
4287           << "Color scale position: " << aColorScale->GetXPosition() << " " << aColorScale->GetYPosition() << "\n"
4288           << "Color scale title: "    << aColorScale->GetTitle() << "\n"
4289           << "Label position: ";
4290     switch (aColorScale->GetLabelPosition())
4291     {
4292       case Aspect_TOCSP_NONE:
4293         theDI << "None\n";
4294         break;
4295       case Aspect_TOCSP_LEFT:
4296         theDI << "Left\n";
4297         break;
4298       case Aspect_TOCSP_RIGHT:
4299         theDI << "Right\n";
4300         break;
4301       case Aspect_TOCSP_CENTER:
4302         theDI << "Center\n";
4303         break;
4304     }
4305     return 0;
4306   }
4307
4308   if (aColorScale.IsNull())
4309   {
4310     aColorScale = new AIS_ColorScale();
4311     aColorScale->SetZLayer (Graphic3d_ZLayerId_TopOSD);
4312     aContext->SetTransformPersistence (aColorScale, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
4313   }
4314
4315   ViewerTest_AutoUpdater anUpdateTool (aContext, aView);
4316   for (Standard_Integer anArgIter = 2; anArgIter < theArgNb; ++anArgIter)
4317   {
4318     Standard_CString        anArg = theArgVec[anArgIter];
4319     TCollection_AsciiString aFlag (anArg);
4320     aFlag.LowerCase();
4321     if (anUpdateTool.parseRedrawMode (aFlag))
4322     {
4323       continue;
4324     }
4325     else if (aFlag == "-range")
4326     {
4327       if (anArgIter + 3 >= theArgNb)
4328       {
4329         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4330         return 1;
4331       }
4332
4333       const TCollection_AsciiString aRangeMin    (theArgVec[++anArgIter]);
4334       const TCollection_AsciiString aRangeMax    (theArgVec[++anArgIter]);
4335       const TCollection_AsciiString aNbIntervals (theArgVec[++anArgIter]);
4336       if (!aRangeMin.IsRealValue()
4337        || !aRangeMax.IsRealValue())
4338       {
4339         std::cout << "Error: the range values should be real!\n";
4340         return 1;
4341       }
4342       else if (!aNbIntervals.IsIntegerValue())
4343       {
4344         std::cout << "Error: the number of intervals should be integer!\n";
4345         return 1;
4346       }
4347
4348       aColorScale->SetRange (aRangeMin.RealValue(), aRangeMax.RealValue());
4349       aColorScale->SetNumberOfIntervals (aNbIntervals.IntegerValue());
4350     }
4351     else if (aFlag == "-font")
4352     {
4353       if (anArgIter + 1 >= theArgNb)
4354       {
4355         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4356         return 1;
4357       }
4358       TCollection_AsciiString aFontArg(theArgVec[anArgIter + 1]);
4359       if (!aFontArg.IsIntegerValue())
4360       {
4361         std::cout << "Error: HeightFont value should be integer!\n";
4362         return 1;
4363       }
4364
4365       aColorScale->SetTextHeight (aFontArg.IntegerValue());
4366       anArgIter += 1;
4367     }
4368     else if (aFlag == "-textpos")
4369     {
4370       if (anArgIter + 1 >= theArgNb)
4371       {
4372         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4373         return 1;
4374       }
4375
4376       TCollection_AsciiString aTextPosArg(theArgVec[++anArgIter]);
4377       aTextPosArg.LowerCase();
4378       Aspect_TypeOfColorScalePosition aLabPosition = Aspect_TOCSP_NONE;
4379       if (aTextPosArg == "none")
4380       {
4381         aLabPosition = Aspect_TOCSP_NONE;
4382       }
4383       else if (aTextPosArg == "left")
4384       {
4385         aLabPosition = Aspect_TOCSP_LEFT;
4386       }
4387       else if (aTextPosArg == "right")
4388       {
4389         aLabPosition = Aspect_TOCSP_RIGHT;
4390       }
4391       else if (aTextPosArg == "center")
4392       {
4393         aLabPosition = Aspect_TOCSP_CENTER;
4394       }
4395       else
4396       {
4397         std::cout << "Error: unknown position '" << aTextPosArg << "'!\n";
4398         return 1;
4399       }
4400       aColorScale->SetLabelPosition (aLabPosition);
4401     }
4402     else if (aFlag == "-logarithmic"
4403           || aFlag == "-log")
4404     {
4405       if (anArgIter + 1 >= theArgNb)
4406       {
4407         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4408         return 1;
4409       }
4410
4411       Standard_Boolean IsLog;
4412       if (!ViewerTest::ParseOnOff(theArgVec[++anArgIter], IsLog))
4413       {
4414         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4415         return 1;
4416       }
4417       aColorScale->SetLogarithmic (IsLog);
4418     }
4419     else if (aFlag == "-huerange"
4420           || aFlag == "-hue")
4421     {
4422       if (anArgIter + 2 >= theArgNb)
4423       {
4424         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4425         return 1;
4426       }
4427
4428       const Standard_Real aHueMin = Draw::Atof (theArgVec[++anArgIter]);
4429       const Standard_Real aHueMax = Draw::Atof (theArgVec[++anArgIter]);
4430       aColorScale->SetHueRange (aHueMin, aHueMax);
4431     }
4432     else if (aFlag == "-colorrange")
4433     {
4434       Quantity_Color aColorMin, aColorMax;
4435       Standard_Integer aNbParsed1 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4436                                                             theArgVec + (anArgIter + 1),
4437                                                             aColorMin);
4438       anArgIter += aNbParsed1;
4439       Standard_Integer aNbParsed2 = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4440                                                             theArgVec + (anArgIter + 1),
4441                                                             aColorMax);
4442       anArgIter += aNbParsed2;
4443       if (aNbParsed1 == 0
4444        || aNbParsed2 == 0)
4445       {
4446         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4447         return 1;
4448       }
4449
4450       aColorScale->SetColorRange (aColorMin, aColorMax);
4451     }
4452     else if (aFlag == "-reversed"
4453           || aFlag == "-inverted"
4454           || aFlag == "-topdown"
4455           || aFlag == "-bottomup")
4456     {
4457       Standard_Boolean toEnable = Standard_True;
4458       if (anArgIter + 1 < theArgNb
4459        && ViewerTest::ParseOnOff(theArgVec[anArgIter + 1], toEnable))
4460       {
4461         ++anArgIter;
4462       }
4463       aColorScale->SetReversed ((aFlag == "-topdown") ? !toEnable : toEnable);
4464     }
4465     else if (aFlag == "-smooth"
4466           || aFlag == "-smoothtransition")
4467     {
4468       Standard_Boolean toEnable = Standard_True;
4469       if (anArgIter + 1 < theArgNb
4470        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4471       {
4472         ++anArgIter;
4473       }
4474       aColorScale->SetSmoothTransition (toEnable);
4475     }
4476     else if (aFlag == "-xy")
4477     {
4478       if (anArgIter + 2 >= theArgNb)
4479       {
4480         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4481         return 1;
4482       }
4483
4484       const TCollection_AsciiString anX (theArgVec[++anArgIter]);
4485       const TCollection_AsciiString anY (theArgVec[++anArgIter]);
4486       if (!anX.IsIntegerValue()
4487        || !anY.IsIntegerValue())
4488       {
4489         std::cout << "Error: coordinates should be integer values!\n";
4490         return 1;
4491       }
4492
4493       aColorScale->SetPosition (anX.IntegerValue(), anY.IntegerValue());
4494     }
4495     else if (aFlag == "-width"
4496           || aFlag == "-w"
4497           || aFlag == "-breadth")
4498     {
4499       if (anArgIter + 1 >= theArgNb)
4500       {
4501         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4502         return 1;
4503       }
4504
4505       const TCollection_AsciiString aBreadth (theArgVec[++anArgIter]);
4506       if (!aBreadth.IsIntegerValue())
4507       {
4508         std::cout << "Error: a width should be an integer value!\n";
4509         return 1;
4510       }
4511       aColorScale->SetBreadth (aBreadth.IntegerValue());
4512     }
4513     else if (aFlag == "-height"
4514           || aFlag == "-h")
4515     {
4516       if (anArgIter + 1 >= theArgNb)
4517       {
4518         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4519         return 1;
4520       }
4521
4522       const TCollection_AsciiString aHeight (theArgVec[++anArgIter]);
4523       if (!aHeight.IsIntegerValue())
4524       {
4525         std::cout << "Error: a width should be an integer value!\n";
4526         return 1;
4527       }
4528       aColorScale->SetHeight (aHeight.IntegerValue());
4529     }
4530     else if (aFlag == "-color")
4531     {
4532       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4533       {
4534         std::cout << "Error: wrong color type! Call -colors before to set user-specified colors!\n";
4535         return 1;
4536       }
4537       else if (anArgIter + 2 >= theArgNb)
4538       {
4539         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4540         return 1;
4541       }
4542
4543       const TCollection_AsciiString anInd (theArgVec[++anArgIter]);
4544       if (!anInd.IsIntegerValue())
4545       {
4546         std::cout << "Error: Index value should be integer!\n";
4547         return 1;
4548       }
4549       const Standard_Integer anIndex = anInd.IntegerValue();
4550       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals())
4551       {
4552         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() <<"!\n";
4553         return 1;
4554       }
4555
4556       Quantity_Color aColor;
4557       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4558                                                            theArgVec + (anArgIter + 1),
4559                                                            aColor);
4560       if (aNbParsed == 0)
4561       {
4562         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
4563         return 1;
4564       }
4565       aColorScale->SetIntervalColor (aColor, anIndex);
4566       aColorScale->SetColorType (Aspect_TOCSD_USER);
4567       anArgIter += aNbParsed;
4568     }
4569     else if (aFlag == "-label")
4570     {
4571       if (aColorScale->GetColorType() != Aspect_TOCSD_USER)
4572       {
4573         std::cout << "Error: wrong label type! Call -labels before to set user-specified labels!\n";
4574         return 1;
4575       }
4576       else if (anArgIter + 2 >= theArgNb)
4577       {
4578         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4579         return 1;
4580       }
4581
4582       Standard_Integer anIndex = Draw::Atoi (theArgVec[anArgIter + 1]);
4583       if (anIndex <= 0 || anIndex > aColorScale->GetNumberOfIntervals() + 1)
4584       {
4585         std::cout << "Error: Index value should be within range 1.." << aColorScale->GetNumberOfIntervals() + 1 <<"!\n";
4586         return 1;
4587       }
4588
4589       TCollection_ExtendedString aText (theArgVec[anArgIter + 2]);
4590       aColorScale->SetLabel     (aText, anIndex);
4591       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4592       anArgIter += 2;
4593     }
4594     else if (aFlag == "-labelat"
4595           || aFlag == "-labat"
4596           || aFlag == "-labelatborder"
4597           || aFlag == "-labatborder"
4598           || aFlag == "-labelatcenter"
4599           || aFlag == "-labatcenter")
4600     {
4601       Standard_Boolean toEnable = Standard_True;
4602       if (aFlag == "-labelat"
4603        || aFlag == "-labat")
4604       {
4605         Standard_Integer aLabAtBorder = -1;
4606         if (++anArgIter >= theArgNb)
4607         {
4608           TCollection_AsciiString anAtBorder (theArgVec[anArgIter]);
4609           anAtBorder.LowerCase();
4610           if (anAtBorder == "border")
4611           {
4612             aLabAtBorder = 1;
4613           }
4614           else if (anAtBorder == "center")
4615           {
4616             aLabAtBorder = 0;
4617           }
4618         }
4619         if (aLabAtBorder == -1)
4620         {
4621           std::cout << "Syntax error at argument '" << anArg << "'!\n";
4622           return 1;
4623         }
4624         toEnable = (aLabAtBorder == 1);
4625       }
4626       else if (anArgIter + 1 < theArgNb
4627             && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
4628       {
4629         ++anArgIter;
4630       }
4631       aColorScale->SetLabelAtBorder (aFlag == "-labelatcenter"
4632                                   || aFlag == "-labatcenter"
4633                                    ? !toEnable
4634                                    :  toEnable);
4635     }
4636     else if (aFlag == "-colors")
4637     {
4638       Aspect_SequenceOfColor aSeq;
4639       for (;;)
4640       {
4641         Quantity_Color aColor;
4642         Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - (anArgIter + 1),
4643                                                              theArgVec + (anArgIter + 1),
4644                                                              aColor);
4645         if (aNbParsed == 0)
4646         {
4647           break;
4648         }
4649         anArgIter += aNbParsed;
4650         aSeq.Append (aColor);
4651       }
4652       if (aSeq.Length() != aColorScale->GetNumberOfIntervals())
4653       {
4654         std::cout << "Error: not enough arguments! You should provide color names or RGB color values for every interval of the "
4655                   << aColorScale->GetNumberOfIntervals() << " intervals\n";
4656         return 1;
4657       }
4658
4659       aColorScale->SetColors    (aSeq);
4660       aColorScale->SetColorType (Aspect_TOCSD_USER);
4661     }
4662     else if (aFlag == "-labels"
4663           || aFlag == "-freelabels")
4664     {
4665       if (anArgIter + 1 >= theArgNb)
4666       {
4667         std::cout << "Syntax error at argument '" << anArg << "'!\n";
4668         return 1;
4669       }
4670
4671       Standard_Integer aNbLabels = aColorScale->IsLabelAtBorder()
4672                                  ? aColorScale->GetNumberOfIntervals() + 1
4673                                  : aColorScale->GetNumberOfIntervals();
4674       if (aFlag == "-freelabels")
4675       {
4676         ++anArgIter;
4677         aNbLabels = Draw::Atoi (theArgVec[anArgIter]);
4678       }
4679       if (anArgIter + aNbLabels >= theArgNb)
4680       {
4681         std::cout << "Error: not enough arguments! " << aNbLabels << " text labels are expected.\n";
4682         return 1;
4683       }
4684
4685       TColStd_SequenceOfExtendedString aSeq;
4686       for (Standard_Integer aLabelIter = 0; aLabelIter < aNbLabels; ++aLabelIter)
4687       {
4688         aSeq.Append (TCollection_ExtendedString (theArgVec[++anArgIter]));
4689       }
4690       aColorScale->SetLabels (aSeq);
4691       aColorScale->SetLabelType (Aspect_TOCSD_USER);
4692     }
4693     else if (aFlag == "-title")
4694     {
4695       if (anArgIter + 1 >= theArgNb)
4696       {
4697         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4698         return 1;
4699       }
4700
4701       Standard_Boolean isTwoArgs = Standard_False;
4702       if (anArgIter + 2 < theArgNb)
4703       {
4704         TCollection_AsciiString aSecondArg (theArgVec[anArgIter + 2]);
4705         aSecondArg.LowerCase();
4706       Standard_DISABLE_DEPRECATION_WARNINGS
4707         if (aSecondArg == "none")
4708         {
4709           aColorScale->SetTitlePosition (Aspect_TOCSP_NONE);
4710           isTwoArgs = Standard_True;
4711         }
4712         else if (aSecondArg == "left")
4713         {
4714           aColorScale->SetTitlePosition (Aspect_TOCSP_LEFT);
4715           isTwoArgs = Standard_True;
4716         }
4717         else if (aSecondArg == "right")
4718         {
4719           aColorScale->SetTitlePosition (Aspect_TOCSP_RIGHT);
4720           isTwoArgs = Standard_True;
4721         }
4722         else if (aSecondArg == "center")
4723         {
4724           aColorScale->SetTitlePosition (Aspect_TOCSP_CENTER);
4725           isTwoArgs = Standard_True;
4726         }
4727       Standard_ENABLE_DEPRECATION_WARNINGS
4728       }
4729
4730       aColorScale->SetTitle (theArgVec[anArgIter + 1]);
4731       if (isTwoArgs)
4732       {
4733         anArgIter += 1;
4734       }
4735       anArgIter += 1;
4736     }
4737     else if (aFlag == "-demoversion"
4738           || aFlag == "-demo")
4739     {
4740       aColorScale->SetPosition (0, 0);
4741       aColorScale->SetTextHeight (16);
4742       aColorScale->SetRange (0.0, 100.0);
4743       aColorScale->SetNumberOfIntervals (10);
4744       aColorScale->SetBreadth (0);
4745       aColorScale->SetHeight  (0);
4746       aColorScale->SetLabelPosition (Aspect_TOCSP_RIGHT);
4747       aColorScale->SetColorType (Aspect_TOCSD_AUTO);
4748       aColorScale->SetLabelType (Aspect_TOCSD_AUTO);
4749     }
4750     else if (aFlag == "-findcolor")
4751     {
4752       if (anArgIter + 1 >= theArgNb)
4753       {
4754         std::cout << "Error: wrong syntax at argument '" << anArg << "'!\n";
4755         return 1;
4756       }
4757
4758       TCollection_AsciiString anArg1 (theArgVec[++anArgIter]);
4759
4760       if (!anArg1.IsRealValue())
4761       {
4762         std::cout << "Error: the value should be real!\n";
4763         return 1;
4764       }
4765
4766       Quantity_Color aColor;
4767       aColorScale->FindColor (anArg1.RealValue(), aColor);
4768       theDI << Quantity_Color::StringName (aColor.Name());
4769       return 0;
4770     }
4771     else
4772     {
4773       std::cout << "Error: wrong syntax at " << anArg << " - unknown argument!\n";
4774       return 1;
4775     }
4776   }
4777
4778   Standard_Integer aWinWidth = 0, aWinHeight = 0;
4779   aView->Window()->Size (aWinWidth, aWinHeight);
4780   if (aColorScale->GetBreadth() == 0)
4781   {
4782     aColorScale->SetBreadth (aWinWidth);
4783   }
4784   if (aColorScale->GetHeight() == 0)
4785   {
4786     aColorScale->SetHeight (aWinHeight);
4787   }
4788   aColorScale->SetToUpdate();
4789   ViewerTest::Display (theArgVec[1], aColorScale, Standard_False, Standard_True);
4790   return 0;
4791 }
4792
4793 //==============================================================================
4794 //function : VGraduatedTrihedron
4795 //purpose  : Displays or hides a graduated trihedron
4796 //==============================================================================
4797 static Standard_Boolean GetColor (const TCollection_AsciiString& theValue,
4798                                   Quantity_Color& theColor)
4799 {
4800   Quantity_NameOfColor aColorName;
4801   TCollection_AsciiString aVal = theValue;
4802   aVal.UpperCase();
4803   if (!Quantity_Color::ColorFromName (aVal.ToCString(), aColorName))
4804   {
4805     return Standard_False;
4806   }
4807   theColor = Quantity_Color (aColorName);
4808   return Standard_True;
4809 }
4810
4811 static int VGraduatedTrihedron (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNum, const char** theArgs)
4812 {
4813   if (theArgNum < 2)
4814   {
4815     std::cout << theArgs[0] << " error: wrong number of parameters. Type 'help"
4816               << theArgs[0] <<"' for more information.\n";
4817     return 1;  //TCL_ERROR
4818   }
4819
4820   NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)> aMapOfArgs;
4821   TCollection_AsciiString aParseKey;
4822   for (Standard_Integer anArgIt = 1; anArgIt < theArgNum; ++anArgIt)
4823   {
4824     TCollection_AsciiString anArg (theArgs [anArgIt]);
4825
4826     if (anArg.Value (1) == '-' && !anArg.IsRealValue())
4827     {
4828       aParseKey = anArg;
4829       aParseKey.Remove (1);
4830       aParseKey.LowerCase();
4831       aMapOfArgs.Bind (aParseKey, new TColStd_HSequenceOfAsciiString);
4832       continue;
4833     }
4834
4835     if (aParseKey.IsEmpty())
4836     {
4837       continue;
4838     }
4839
4840     aMapOfArgs(aParseKey)->Append (anArg);
4841   }
4842
4843   // Check parameters
4844   for (NCollection_DataMap<TCollection_AsciiString, Handle(TColStd_HSequenceOfAsciiString)>::Iterator aMapIt (aMapOfArgs);
4845        aMapIt.More(); aMapIt.Next())
4846   {
4847     const TCollection_AsciiString& aKey = aMapIt.Key();
4848     const Handle(TColStd_HSequenceOfAsciiString)& anArgs = aMapIt.Value();
4849
4850     // Bool key, without arguments
4851     if ((aKey.IsEqual ("on") || aKey.IsEqual ("off"))
4852         && anArgs->IsEmpty())
4853     {
4854       continue;
4855     }
4856
4857     // One argument
4858     if ( (aKey.IsEqual ("xname") || aKey.IsEqual ("yname") || aKey.IsEqual ("zname"))
4859           && anArgs->Length() == 1)
4860     {
4861       continue;
4862     }
4863
4864     // On/off arguments
4865     if ((aKey.IsEqual ("xdrawname") || aKey.IsEqual ("ydrawname") || aKey.IsEqual ("zdrawname")
4866         || aKey.IsEqual ("xdrawticks") || aKey.IsEqual ("ydrawticks") || aKey.IsEqual ("zdrawticks")
4867         || aKey.IsEqual ("xdrawvalues") || aKey.IsEqual ("ydrawvalues") || aKey.IsEqual ("zdrawvalues")
4868         || aKey.IsEqual ("drawgrid") || aKey.IsEqual ("drawaxes"))
4869         && anArgs->Length() == 1 && (anArgs->Value(1).IsEqual ("on") || anArgs->Value(1).IsEqual ("off")))
4870     {
4871       continue;
4872     }
4873
4874     // One string argument
4875     if ( (aKey.IsEqual ("xnamecolor") || aKey.IsEqual ("ynamecolor") || aKey.IsEqual ("znamecolor")
4876           || aKey.IsEqual ("xcolor") || aKey.IsEqual ("ycolor") || aKey.IsEqual ("zcolor"))
4877           && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4878     {
4879       continue;
4880     }
4881
4882     // One integer argument
4883     if ( (aKey.IsEqual ("xticks") || aKey.IsEqual ("yticks") || aKey.IsEqual ("zticks")
4884           || aKey.IsEqual ("xticklength") || aKey.IsEqual ("yticklength") || aKey.IsEqual ("zticklength")
4885           || aKey.IsEqual ("xnameoffset") || aKey.IsEqual ("ynameoffset") || aKey.IsEqual ("znameoffset")
4886           || aKey.IsEqual ("xvaluesoffset") || aKey.IsEqual ("yvaluesoffset") || aKey.IsEqual ("zvaluesoffset"))
4887          && anArgs->Length() == 1 && anArgs->Value(1).IsIntegerValue())
4888     {
4889       continue;
4890     }
4891
4892     // One real argument
4893     if ( aKey.IsEqual ("arrowlength")
4894          && anArgs->Length() == 1 && (anArgs->Value(1).IsIntegerValue() || anArgs->Value(1).IsRealValue()))
4895     {
4896       continue;
4897     }
4898
4899     // Two string arguments
4900     if ( (aKey.IsEqual ("namefont") || aKey.IsEqual ("valuesfont"))
4901          && anArgs->Length() == 1 && !anArgs->Value(1).IsIntegerValue() && !anArgs->Value(1).IsRealValue())
4902     {
4903       continue;
4904     }
4905
4906     TCollection_AsciiString aLowerKey;
4907     aLowerKey  = "-";
4908     aLowerKey += aKey;
4909     aLowerKey.LowerCase();
4910     std::cout << theArgs[0] << ": " << aLowerKey << " is unknown option, or the arguments are unacceptable.\n";
4911     std::cout << "Type help for more information.\n";
4912     return 1;
4913   }
4914
4915   Handle(AIS_InteractiveContext) anAISContext = ViewerTest::GetAISContext();
4916   if (anAISContext.IsNull())
4917   {
4918     std::cout << theArgs[0] << ":  please use 'vinit' command to initialize view.\n";
4919     return 1;
4920   }
4921
4922   Standard_Boolean toDisplay = Standard_True;
4923   Quantity_Color aColor;
4924   Graphic3d_GraduatedTrihedron aTrihedronData;
4925   // Process parameters
4926   Handle(TColStd_HSequenceOfAsciiString) aValues;
4927   if (aMapOfArgs.Find ("off", aValues))
4928   {
4929     toDisplay = Standard_False;
4930   }
4931
4932   // AXES NAMES
4933   if (aMapOfArgs.Find ("xname", aValues))
4934   {
4935     aTrihedronData.ChangeXAxisAspect().SetName (aValues->Value(1));
4936   }
4937   if (aMapOfArgs.Find ("yname", aValues))
4938   {
4939     aTrihedronData.ChangeYAxisAspect().SetName (aValues->Value(1));
4940   }
4941   if (aMapOfArgs.Find ("zname", aValues))
4942   {
4943     aTrihedronData.ChangeZAxisAspect().SetName (aValues->Value(1));
4944   }
4945   if (aMapOfArgs.Find ("xdrawname", aValues))
4946   {
4947     aTrihedronData.ChangeXAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4948   }
4949   if (aMapOfArgs.Find ("ydrawname", aValues))
4950   {
4951     aTrihedronData.ChangeYAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4952   }
4953   if (aMapOfArgs.Find ("zdrawname", aValues))
4954   {
4955     aTrihedronData.ChangeZAxisAspect().SetDrawName (aValues->Value(1).IsEqual ("on"));
4956   }
4957   if (aMapOfArgs.Find ("xnameoffset", aValues))
4958   {
4959     aTrihedronData.ChangeXAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4960   }
4961   if (aMapOfArgs.Find ("ynameoffset", aValues))
4962   {
4963     aTrihedronData.ChangeYAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4964   }
4965   if (aMapOfArgs.Find ("znameoffset", aValues))
4966   {
4967     aTrihedronData.ChangeZAxisAspect().SetNameOffset (aValues->Value(1).IntegerValue());
4968   }
4969
4970   // COLORS
4971   if (aMapOfArgs.Find ("xnamecolor", aValues))
4972   {
4973     if (!GetColor (aValues->Value(1), aColor))
4974     {
4975       std::cout << theArgs[0] << "error: -xnamecolor wrong color name.\n";
4976       return 1;
4977     }
4978     aTrihedronData.ChangeXAxisAspect().SetNameColor (aColor);
4979   }
4980   if (aMapOfArgs.Find ("ynamecolor", aValues))
4981   {
4982     if (!GetColor (aValues->Value(1), aColor))
4983     {
4984       std::cout << theArgs[0] << "error: -ynamecolor wrong color name.\n";
4985       return 1;
4986     }
4987     aTrihedronData.ChangeYAxisAspect().SetNameColor (aColor);
4988   }
4989   if (aMapOfArgs.Find ("znamecolor", aValues))
4990   {
4991     if (!GetColor (aValues->Value(1), aColor))
4992     {
4993       std::cout << theArgs[0] << "error: -znamecolor wrong color name.\n";
4994       return 1;
4995     }
4996     aTrihedronData.ChangeZAxisAspect().SetNameColor (aColor);
4997   }
4998   if (aMapOfArgs.Find ("xcolor", aValues))
4999   {
5000     if (!GetColor (aValues->Value(1), aColor))
5001     {
5002       std::cout << theArgs[0] << "error: -xcolor wrong color name.\n";
5003       return 1;
5004     }
5005     aTrihedronData.ChangeXAxisAspect().SetColor (aColor);
5006   }
5007   if (aMapOfArgs.Find ("ycolor", aValues))
5008   {
5009     if (!GetColor (aValues->Value(1), aColor))
5010     {
5011       std::cout << theArgs[0] << "error: -ycolor wrong color name.\n";
5012       return 1;
5013     }
5014     aTrihedronData.ChangeYAxisAspect().SetColor (aColor);
5015   }
5016   if (aMapOfArgs.Find ("zcolor", aValues))
5017   {
5018     if (!GetColor (aValues->Value(1), aColor))
5019     {
5020       std::cout << theArgs[0] << "error: -zcolor wrong color name.\n";
5021       return 1;
5022     }
5023     aTrihedronData.ChangeZAxisAspect().SetColor (aColor);
5024   }
5025
5026   // TICKMARKS
5027   if (aMapOfArgs.Find ("xticks", aValues))
5028   {
5029     aTrihedronData.ChangeXAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5030   }
5031   if (aMapOfArgs.Find ("yticks", aValues))
5032   {
5033     aTrihedronData.ChangeYAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5034   }
5035   if (aMapOfArgs.Find ("zticks", aValues))
5036   {
5037     aTrihedronData.ChangeZAxisAspect().SetTickmarksNumber (aValues->Value(1).IntegerValue());
5038   }
5039   if (aMapOfArgs.Find ("xticklength", aValues))
5040   {
5041     aTrihedronData.ChangeXAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5042   }
5043   if (aMapOfArgs.Find ("yticklength", aValues))
5044   {
5045     aTrihedronData.ChangeYAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5046   }
5047   if (aMapOfArgs.Find ("zticklength", aValues))
5048   {
5049     aTrihedronData.ChangeZAxisAspect().SetTickmarksLength (aValues->Value(1).IntegerValue());
5050   }
5051   if (aMapOfArgs.Find ("xdrawticks", aValues))
5052   {
5053     aTrihedronData.ChangeXAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5054   }
5055   if (aMapOfArgs.Find ("ydrawticks", aValues))
5056   {
5057     aTrihedronData.ChangeYAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5058   }
5059   if (aMapOfArgs.Find ("zdrawticks", aValues))
5060   {
5061     aTrihedronData.ChangeZAxisAspect().SetDrawTickmarks (aValues->Value(1).IsEqual ("on"));
5062   }
5063
5064   // VALUES
5065   if (aMapOfArgs.Find ("xdrawvalues", aValues))
5066   {
5067     aTrihedronData.ChangeXAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5068   }
5069   if (aMapOfArgs.Find ("ydrawvalues", aValues))
5070   {
5071     aTrihedronData.ChangeYAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5072   }
5073   if (aMapOfArgs.Find ("zdrawvalues", aValues))
5074   {
5075     aTrihedronData.ChangeZAxisAspect().SetDrawValues (aValues->Value(1).IsEqual ("on"));
5076   }
5077   if (aMapOfArgs.Find ("xvaluesoffset", aValues))
5078   {
5079     aTrihedronData.ChangeXAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5080   }
5081   if (aMapOfArgs.Find ("yvaluesoffset", aValues))
5082   {
5083     aTrihedronData.ChangeYAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5084   }
5085   if (aMapOfArgs.Find ("zvaluesoffset", aValues))
5086   {
5087     aTrihedronData.ChangeZAxisAspect().SetValuesOffset (aValues->Value(1).IntegerValue());
5088   }
5089
5090   // ARROWS
5091   if (aMapOfArgs.Find ("arrowlength", aValues))
5092   {
5093     aTrihedronData.SetArrowsLength ((Standard_ShortReal) aValues->Value(1).RealValue());
5094   }
5095
5096   // FONTS
5097   if (aMapOfArgs.Find ("namefont", aValues))
5098   {
5099     aTrihedronData.SetNamesFont (aValues->Value(1));
5100   }
5101   if (aMapOfArgs.Find ("valuesfont", aValues))
5102   {
5103     aTrihedronData.SetValuesFont (aValues->Value(1));
5104   }
5105
5106   if (aMapOfArgs.Find ("drawgrid", aValues))
5107   {
5108     aTrihedronData.SetDrawGrid (aValues->Value(1).IsEqual ("on"));
5109   }
5110   if (aMapOfArgs.Find ("drawaxes", aValues))
5111   {
5112     aTrihedronData.SetDrawAxes (aValues->Value(1).IsEqual ("on"));
5113   }
5114
5115   // The final step: display of erase trihedron
5116   if (toDisplay)
5117   {
5118     ViewerTest::CurrentView()->GraduatedTrihedronDisplay (aTrihedronData);
5119   }
5120   else
5121   {
5122     ViewerTest::CurrentView()->GraduatedTrihedronErase();
5123   }
5124
5125   ViewerTest::GetAISContext()->UpdateCurrentViewer();
5126   ViewerTest::CurrentView()->Redraw();
5127
5128   return 0;
5129 }
5130
5131 //==============================================================================
5132 //function : VTile
5133 //purpose  :
5134 //==============================================================================
5135 static int VTile (Draw_Interpretor& theDI,
5136                   Standard_Integer  theArgNb,
5137                   const char**      theArgVec)
5138 {
5139   Handle(V3d_View) aView = ViewerTest::CurrentView();
5140   if (aView.IsNull())
5141   {
5142     std::cerr << "Error: no active viewer.\n";
5143     return 1;
5144   }
5145
5146   Graphic3d_CameraTile aTile = aView->Camera()->Tile();
5147   if (theArgNb < 2)
5148   {
5149     theDI << "Total size: " << aTile.TotalSize.x() << " " << aTile.TotalSize.y() << "\n"
5150           << "Tile  size: " << aTile.TileSize.x()  << " " << aTile.TileSize.y()  << "\n"
5151           << "Lower left: " << aTile.Offset.x()    << " " << aTile.Offset.y()    << "\n";
5152     return 0;
5153   }
5154
5155   aView->Window()->Size (aTile.TileSize.x(), aTile.TileSize.y());
5156   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5157   {
5158     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5159     anArg.LowerCase();
5160     if (anArg == "-lowerleft"
5161      || anArg == "-upperleft")
5162     {
5163       if (anArgIter + 3 < theArgNb)
5164       {
5165         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5166         return 1;
5167       }
5168       aTile.IsTopDown = (anArg == "-upperleft") == Standard_True;
5169       aTile.Offset.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5170       aTile.Offset.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5171     }
5172     else if (anArg == "-total"
5173           || anArg == "-totalsize"
5174           || anArg == "-viewsize")
5175     {
5176       if (anArgIter + 3 < theArgNb)
5177       {
5178         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5179         return 1;
5180       }
5181       aTile.TotalSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5182       aTile.TotalSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5183       if (aTile.TotalSize.x() < 1
5184        || aTile.TotalSize.y() < 1)
5185       {
5186         std::cerr << "Error: total size is incorrect.\n";
5187         return 1;
5188       }
5189     }
5190     else if (anArg == "-tilesize")
5191     {
5192       if (anArgIter + 3 < theArgNb)
5193       {
5194         std::cerr << "Syntax error at '" << theArgVec[anArgIter] << "'.\n";
5195         return 1;
5196       }
5197
5198       aTile.TileSize.x() = Draw::Atoi (theArgVec[anArgIter + 1]);
5199       aTile.TileSize.y() = Draw::Atoi (theArgVec[anArgIter + 2]);
5200       if (aTile.TileSize.x() < 1
5201        || aTile.TileSize.y() < 1)
5202       {
5203         std::cerr << "Error: tile size is incorrect.\n";
5204         return 1;
5205       }
5206     }
5207     else if (anArg == "-unset")
5208     {
5209       aView->Camera()->SetTile (Graphic3d_CameraTile());
5210       aView->Redraw();
5211       return 0;
5212     }
5213   }
5214
5215   if (aTile.TileSize.x() < 1
5216    || aTile.TileSize.y() < 1)
5217   {
5218     std::cerr << "Error: tile size is undefined.\n";
5219     return 1;
5220   }
5221   else if (aTile.TotalSize.x() < 1
5222         || aTile.TotalSize.y() < 1)
5223   {
5224     std::cerr << "Error: total size is undefined.\n";
5225     return 1;
5226   }
5227
5228   aView->Camera()->SetTile (aTile);
5229   aView->Redraw();
5230   return 0;
5231 }
5232
5233 //! Format ZLayer ID.
5234 inline const char* formZLayerId (const Standard_Integer theLayerId)
5235 {
5236   switch (theLayerId)
5237   {
5238     case Graphic3d_ZLayerId_UNKNOWN: return "[INVALID]";
5239     case Graphic3d_ZLayerId_Default: return "[DEFAULT]";
5240     case Graphic3d_ZLayerId_Top:     return "[TOP]";
5241     case Graphic3d_ZLayerId_Topmost: return "[TOPMOST]";
5242     case Graphic3d_ZLayerId_TopOSD:  return "[OVERLAY]";
5243     case Graphic3d_ZLayerId_BotOSD:  return "[UNDERLAY]";
5244   }
5245   return "";
5246 }
5247
5248 //! Print the ZLayer information.
5249 inline void printZLayerInfo (Draw_Interpretor& theDI,
5250                              const Graphic3d_ZLayerSettings& theLayer)
5251 {
5252   if (!theLayer.Name().IsEmpty())
5253   {
5254     theDI << "  Name: " << theLayer.Name() << "\n";
5255   }
5256   if (theLayer.IsImmediate())
5257   {
5258     theDI << "  Immediate: TRUE\n";
5259   }
5260   theDI << "  Origin: " << theLayer.Origin().X() << " " << theLayer.Origin().Y() << " " << theLayer.Origin().Z() << "\n";
5261   theDI << "  Culling distance: "      << theLayer.CullingDistance() << "\n";
5262   theDI << "  Culling size: "          << theLayer.CullingSize() << "\n";
5263   theDI << "  Depth test:   "          << (theLayer.ToEnableDepthTest() ? "enabled" : "disabled") << "\n";
5264   theDI << "  Depth write:  "          << (theLayer.ToEnableDepthWrite() ? "enabled" : "disabled") << "\n";
5265   theDI << "  Depth buffer clearing: " << (theLayer.ToClearDepth() ? "enabled" : "disabled") << "\n";
5266   if (theLayer.PolygonOffset().Mode != Aspect_POM_None)
5267   {
5268     theDI << "  Depth offset: " << theLayer.PolygonOffset().Factor << " " << theLayer.PolygonOffset().Units << "\n";
5269   }
5270 }
5271
5272 //==============================================================================
5273 //function : VZLayer
5274 //purpose  : Test z layer operations for v3d viewer
5275 //==============================================================================
5276 static int VZLayer (Draw_Interpretor& theDI,
5277                     Standard_Integer  theArgNb,
5278                     const char**      theArgVec)
5279 {
5280   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
5281   if (aContextAIS.IsNull())
5282   {
5283     std::cout << "No active viewer!\n";
5284     return 1;
5285   }
5286
5287   const Handle(V3d_Viewer)& aViewer = aContextAIS->CurrentViewer();
5288   if (theArgNb < 2)
5289   {
5290     TColStd_SequenceOfInteger aLayers;
5291     aViewer->GetAllZLayers (aLayers);
5292     for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5293     {
5294       theDI << "ZLayer " << aLayeriter.Value() << " " << formZLayerId (aLayeriter.Value()) << "\n";
5295       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
5296       printZLayerInfo (theDI, aSettings);
5297     }
5298     return 1;
5299   }
5300
5301   Standard_Integer anArgIter = 1;
5302   Standard_Integer aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5303   ViewerTest_AutoUpdater anUpdateTool (aContextAIS, ViewerTest::CurrentView());
5304   if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5305   {
5306     ++anArgIter;
5307   }
5308
5309   {
5310     TCollection_AsciiString aFirstArg (theArgVec[anArgIter]);
5311     if (aFirstArg.IsIntegerValue())
5312     {
5313       ++anArgIter;
5314       aLayerId = aFirstArg.IntegerValue();
5315     }
5316     else
5317     {
5318       if (ViewerTest::ParseZLayerName (aFirstArg.ToCString(), aLayerId))
5319       {
5320         ++anArgIter;
5321       }
5322     }
5323   }
5324
5325   for (; anArgIter < theArgNb; ++anArgIter)
5326   {
5327     // perform operation
5328     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5329     anArg.LowerCase();
5330     if (anUpdateTool.parseRedrawMode (anArg))
5331     {
5332       //
5333     }
5334     else if (anArg == "-add"
5335           || anArg == "add")
5336     {
5337       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5338       if (!aViewer->AddZLayer (aLayerId))
5339       {
5340         std::cout << "Error: can not add a new z layer!\n";
5341         return 0;
5342       }
5343
5344       theDI << aLayerId;
5345     }
5346     else if (anArg == "-del"
5347           || anArg == "-delete"
5348           || anArg == "del")
5349     {
5350       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5351       {
5352         if (++anArgIter >= theArgNb)
5353         {
5354           std::cout << "Syntax error: id of z layer to remove is missing\n";
5355           return 1;
5356         }
5357
5358         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5359       }
5360
5361       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5362        || aLayerId == Graphic3d_ZLayerId_Default
5363        || aLayerId == Graphic3d_ZLayerId_Top
5364        || aLayerId == Graphic3d_ZLayerId_Topmost
5365        || aLayerId == Graphic3d_ZLayerId_TopOSD
5366        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5367       {
5368         std::cout << "Syntax error: standard Z layer can not be removed\n";
5369         return 1;
5370       }
5371
5372       // move all object displayed in removing layer to default layer
5373       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5374            anObjIter.More(); anObjIter.Next())
5375       {
5376         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5377         if (aPrs.IsNull()
5378          || aPrs->ZLayer() != aLayerId)
5379         {
5380           continue;
5381         }
5382         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5383       }
5384
5385       if (!aViewer->RemoveZLayer (aLayerId))
5386       {
5387         std::cout << "Z layer can not be removed!\n";
5388       }
5389       else
5390       {
5391         theDI << aLayerId << " ";
5392       }
5393     }
5394     else if (anArg == "-get"
5395           || anArg == "get")
5396     {
5397       TColStd_SequenceOfInteger aLayers;
5398       aViewer->GetAllZLayers (aLayers);
5399       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5400       {
5401         theDI << aLayeriter.Value() << " ";
5402       }
5403
5404       theDI << "\n";
5405     }
5406     else if (anArg == "-name")
5407     {
5408       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5409       {
5410         std::cout << "Syntax error: id of Z layer is missing\n";
5411         return 1;
5412       }
5413
5414       if (++anArgIter >= theArgNb)
5415       {
5416         std::cout << "Syntax error: name is missing\n";
5417         return 1;
5418       }
5419
5420       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5421       aSettings.SetName (theArgVec[anArgIter]);
5422       aViewer->SetZLayerSettings (aLayerId, aSettings);
5423     }
5424     else if (anArg == "-origin")
5425     {
5426       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5427       {
5428         std::cout << "Syntax error: id of Z layer is missing\n";
5429         return 1;
5430       }
5431
5432       if (anArgIter + 2 >= theArgNb)
5433       {
5434         std::cout << "Syntax error: origin coordinates are missing\n";
5435         return 1;
5436       }
5437
5438       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5439       gp_XYZ anOrigin;
5440       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5441       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5442       anOrigin.SetZ (0.0);
5443       if (anArgIter + 3 < theArgNb)
5444       {
5445         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5446         anArgIter += 3;
5447       }
5448       else
5449       {
5450         anArgIter += 2;
5451       }
5452       aSettings.SetOrigin (anOrigin);
5453       aViewer->SetZLayerSettings (aLayerId, aSettings);
5454     }
5455     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5456           && anArgIter + 1 < theArgNb
5457           && (anArg == "-cullingdistance"
5458            || anArg == "-cullingdist"
5459            || anArg == "-culldistance"
5460            || anArg == "-culldist"
5461            || anArg == "-distcull"
5462            || anArg == "-distculling"
5463            || anArg == "-distanceculling"))
5464     {
5465       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5466       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5467       aSettings.SetCullingDistance (aDist);
5468       aViewer->SetZLayerSettings (aLayerId, aSettings);
5469     }
5470     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5471           && anArgIter + 1 < theArgNb
5472           && (anArg == "-cullingsize"
5473            || anArg == "-cullsize"
5474            || anArg == "-sizecull"
5475            || anArg == "-sizeculling"))
5476     {
5477       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5478       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5479       aSettings.SetCullingSize (aSize);
5480       aViewer->SetZLayerSettings (aLayerId, aSettings);
5481     }
5482     else if (anArg == "-settings"
5483           || anArg == "settings")
5484     {
5485       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5486       {
5487         if (++anArgIter >= theArgNb)
5488         {
5489           std::cout << "Syntax error: id of Z layer is missing\n";
5490           return 1;
5491         }
5492
5493         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5494       }
5495
5496       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5497       printZLayerInfo (theDI, aSettings);
5498     }
5499     else if (anArg == "-enable"
5500           || anArg == "enable"
5501           || anArg == "-disable"
5502           || anArg == "disable")
5503     {
5504       const Standard_Boolean toEnable = anArg == "-enable"
5505                                      || anArg == "enable";
5506       if (++anArgIter >= theArgNb)
5507       {
5508         std::cout << "Syntax error: option name is missing\n";
5509         return 1;
5510       }
5511
5512       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5513       aSubOp.LowerCase();
5514       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5515       {
5516         if (++anArgIter >= theArgNb)
5517         {
5518           std::cout << "Syntax error: id of Z layer is missing\n";
5519           return 1;
5520         }
5521
5522         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5523       }
5524
5525       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5526       if (aSubOp == "depthtest"
5527        || aSubOp == "test")
5528       {
5529         aSettings.SetEnableDepthTest (toEnable);
5530       }
5531       else if (aSubOp == "depthwrite"
5532             || aSubOp == "write")
5533       {
5534         aSettings.SetEnableDepthWrite (toEnable);
5535       }
5536       else if (aSubOp == "depthclear"
5537             || aSubOp == "clear")
5538       {
5539         aSettings.SetClearDepth (toEnable);
5540       }
5541       else if (aSubOp == "depthoffset"
5542             || aSubOp == "offset")
5543       {
5544         Graphic3d_PolygonOffset aParams;
5545         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5546         if (toEnable)
5547         {
5548           if (anArgIter + 2 >= theArgNb)
5549           {
5550             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5551             return 1;
5552           }
5553
5554           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5555           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5556         }
5557         aSettings.SetPolygonOffset (aParams);
5558       }
5559       else if (aSubOp == "positiveoffset"
5560             || aSubOp == "poffset")
5561       {
5562         if (toEnable)
5563         {
5564           aSettings.SetDepthOffsetPositive();
5565         }
5566         else
5567         {
5568           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5569         }
5570       }
5571       else if (aSubOp == "negativeoffset"
5572             || aSubOp == "noffset")
5573       {
5574         if (toEnable)
5575         {
5576           aSettings.SetDepthOffsetNegative();
5577         }
5578         else
5579         {
5580           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5581         }
5582       }
5583       else if (aSubOp == "textureenv")
5584       {
5585         aSettings.SetEnvironmentTexture (toEnable);
5586       }
5587
5588       aViewer->SetZLayerSettings (aLayerId, aSettings);
5589     }
5590     else
5591     {
5592       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5593       return 1;
5594     }
5595   }
5596
5597   return 0;
5598 }
5599
5600 // The interactive presentation of 2d layer item
5601 // for "vlayerline" command it provides a presentation of
5602 // line with user-defined linewidth, linetype and transparency.
5603 class V3d_LineItem : public AIS_InteractiveObject
5604 {
5605 public:
5606   // CASCADE RTTI
5607   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5608
5609   // constructor
5610   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5611                                Standard_Real X2, Standard_Real Y2,
5612                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5613                                Standard_Real theWidth    = 0.5,
5614                                Standard_Real theTransp   = 1.0);
5615
5616   private:
5617
5618   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5619                 const Handle(Prs3d_Presentation)& thePresentation,
5620                 const Standard_Integer theMode) Standard_OVERRIDE;
5621
5622   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5623                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5624   {}
5625
5626 private:
5627
5628   Standard_Real       myX1, myY1, myX2, myY2;
5629   Aspect_TypeOfLine   myType;
5630   Standard_Real       myWidth;
5631 };
5632
5633 // default constructor for line item
5634 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5635                            Standard_Real X2, Standard_Real Y2,
5636                            Aspect_TypeOfLine theType,
5637                            Standard_Real theWidth,
5638                            Standard_Real theTransp) :
5639   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5640   myType(theType), myWidth(theWidth)
5641 {
5642   SetTransparency (1-theTransp);
5643 }
5644
5645 // render line
5646 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5647                             const Handle(Prs3d_Presentation)& thePresentation,
5648                             const Standard_Integer /*theMode*/)
5649 {
5650   thePresentation->Clear();
5651   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5652   Standard_Integer aWidth, aHeight;
5653   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5654   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5655   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5656   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5657   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5658   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5659   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5660   aGroup->AddPrimitiveArray (aPrim);
5661 }
5662
5663 //=============================================================================
5664 //function : VLayerLine
5665 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5666 //         : linewidth, transparency coefficient
5667 //============================================================================
5668 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5669 {
5670   // get the active view
5671   Handle(V3d_View) aView = ViewerTest::CurrentView();
5672   if (aView.IsNull())
5673   {
5674     di << "Call vinit before!\n";
5675     return 1;
5676   }
5677   else if (argc < 5)
5678   {
5679     di << "Use: " << argv[0];
5680     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5681     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5682     di << "              0 - solid  \n";
5683     di << "              1 - dashed \n";
5684     di << "              2 - dot    \n";
5685     di << "              3 - dashdot\n";
5686     di << " transparency : { 0.0 - 1.0 } \n";
5687     di << "                  0.0 - transparent\n";
5688     di << "                  1.0 - visible    \n";
5689     return 1;
5690   }
5691
5692   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5693   // get the input params
5694   Standard_Real X1 = Draw::Atof(argv[1]);
5695   Standard_Real Y1 = Draw::Atof(argv[2]);
5696   Standard_Real X2 = Draw::Atof(argv[3]);
5697   Standard_Real Y2 = Draw::Atof(argv[4]);
5698
5699   Standard_Real aWidth = 0.5;
5700   Standard_Real aTransparency = 1.0;
5701
5702   // has width
5703   if (argc > 5)
5704     aWidth = Draw::Atof(argv[5]);
5705
5706   // select appropriate line type
5707   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5708   if (argc > 6
5709   && !ViewerTest::ParseLineType (argv[6], aLineType))
5710   {
5711     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5712     return 1;
5713   }
5714
5715   // has transparency
5716   if (argc > 7)
5717   {
5718     aTransparency = Draw::Atof(argv[7]);
5719     if (aTransparency < 0 || aTransparency > 1.0)
5720       aTransparency = 1.0;
5721   }
5722
5723   static Handle (V3d_LineItem) aLine;
5724   if (!aLine.IsNull())
5725   {
5726     aContext->Erase (aLine, Standard_False);
5727   }
5728   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5729                             aLineType, aWidth,
5730                             aTransparency);
5731
5732   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5733   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5734   aLine->SetToUpdate();
5735   aContext->Display (aLine, Standard_True);
5736
5737   return 0;
5738 }
5739
5740
5741 //==============================================================================
5742 //function : VGrid
5743 //purpose  :
5744 //==============================================================================
5745
5746 static int VGrid (Draw_Interpretor& /*theDI*/,
5747                   Standard_Integer  theArgNb,
5748                   const char**      theArgVec)
5749 {
5750   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5751   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5752   if (aView.IsNull() || aViewer.IsNull())
5753   {
5754     std::cerr << "Error: no active view\n";
5755     return 1;
5756   }
5757
5758   Aspect_GridType     aType = aViewer->GridType();
5759   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5760   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5761   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5762   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5763   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5764   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5765   {
5766     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5767     anArg.LowerCase();
5768     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5769     {
5770       continue;
5771     }
5772     else if (anArgIter + 1 < theArgNb
5773           && anArg == "-type")
5774     {
5775       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5776       anArgNext.LowerCase();
5777       if (anArgNext == "r"
5778        || anArgNext == "rect"
5779        || anArgNext == "rectangular")
5780       {
5781         aType = Aspect_GT_Rectangular;
5782       }
5783       else if (anArgNext == "c"
5784             || anArgNext == "circ"
5785             || anArgNext == "circular")
5786       {
5787         aType = Aspect_GT_Circular;
5788       }
5789       else
5790       {
5791         std::cout << "Syntax error at '" << anArgNext << "'\n";
5792         return 1;
5793       }
5794     }
5795     else if (anArgIter + 1 < theArgNb
5796           && anArg == "-mode")
5797     {
5798       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5799       anArgNext.LowerCase();
5800       if (anArgNext == "l"
5801        || anArgNext == "line"
5802        || anArgNext == "lines")
5803       {
5804         aMode = Aspect_GDM_Lines;
5805       }
5806       else if (anArgNext == "p"
5807             || anArgNext == "point"
5808             || anArgNext == "points")
5809       {
5810         aMode = Aspect_GDM_Points;
5811       }
5812       else
5813       {
5814         std::cout << "Syntax error at '" << anArgNext << "'\n";
5815         return 1;
5816       }
5817     }
5818     else if (anArgIter + 2 < theArgNb
5819           && (anArg == "-origin"
5820            || anArg == "-orig"))
5821     {
5822       hasOrigin = true;
5823       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5824                               Draw::Atof (theArgVec[anArgIter + 2]));
5825       anArgIter += 2;
5826     }
5827     else if (anArgIter + 2 < theArgNb
5828           && anArg == "-step")
5829     {
5830       hasStep = true;
5831       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5832                             Draw::Atof (theArgVec[anArgIter + 2]));
5833       if (aNewStepXY.x() <= 0.0
5834        || aNewStepXY.y() <= 0.0)
5835       {
5836         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5837         return 1;
5838       }
5839       anArgIter += 2;
5840     }
5841     else if (anArgIter + 1 < theArgNb
5842           && (anArg == "-angle"
5843            || anArg == "-rotangle"
5844            || anArg == "-rotationangle"))
5845     {
5846       hasRotAngle = true;
5847       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
5848     }
5849     else if (anArgIter + 1 < theArgNb
5850           && (anArg == "-zoffset"
5851            || anArg == "-dz"))
5852     {
5853       hasZOffset = true;
5854       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
5855     }
5856     else if (anArgIter + 1 < theArgNb
5857           && anArg == "-radius")
5858     {
5859       hasSize = true;
5860       ++anArgIter;
5861       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
5862       if (aNewStepXY.x() <= 0.0)
5863       {
5864         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
5865         return 1;
5866       }
5867     }
5868     else if (anArgIter + 2 < theArgNb
5869           && anArg == "-size")
5870     {
5871       hasSize = true;
5872       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5873                             Draw::Atof (theArgVec[anArgIter + 2]));
5874       if (aNewStepXY.x() <= 0.0
5875        || aNewStepXY.y() <= 0.0)
5876       {
5877         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5878         return 1;
5879       }
5880       anArgIter += 2;
5881     }
5882     else if (anArg == "r"
5883           || anArg == "rect"
5884           || anArg == "rectangular")
5885     {
5886       aType = Aspect_GT_Rectangular;
5887     }
5888     else if (anArg == "c"
5889           || anArg == "circ"
5890           || anArg == "circular")
5891     {
5892       aType = Aspect_GT_Circular;
5893     }
5894     else if (anArg == "l"
5895           || anArg == "line"
5896           || anArg == "lines")
5897     {
5898       aMode = Aspect_GDM_Lines;
5899     }
5900     else if (anArg == "p"
5901           || anArg == "point"
5902           || anArg == "points")
5903     {
5904       aMode = Aspect_GDM_Points;
5905     }
5906     else if (anArgIter + 1 >= theArgNb
5907           && anArg == "off")
5908     {
5909       aViewer->DeactivateGrid();
5910       return 0;
5911     }
5912     else
5913     {
5914       std::cout << "Syntax error at '" << anArg << "'\n";
5915       return 1;
5916     }
5917   }
5918
5919   if (aType == Aspect_GT_Rectangular)
5920   {
5921     Graphic3d_Vec2d anOrigXY, aStepXY;
5922     Standard_Real aRotAngle = 0.0;
5923     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5924     if (hasOrigin)
5925     {
5926       anOrigXY = aNewOriginXY;
5927     }
5928     if (hasStep)
5929     {
5930       aStepXY = aNewStepXY;
5931     }
5932     if (hasRotAngle)
5933     {
5934       aRotAngle = aNewRotAngle;
5935     }
5936     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5937     if (hasSize || hasZOffset)
5938     {
5939       Graphic3d_Vec3d aSize;
5940       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5941       if (hasSize)
5942       {
5943         aSize.x() = aNewSizeXY.x();
5944         aSize.y() = aNewSizeXY.y();
5945       }
5946       if (hasZOffset)
5947       {
5948         aSize.z() = aNewZOffset;
5949       }
5950       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5951     }
5952   }
5953   else if (aType == Aspect_GT_Circular)
5954   {
5955     Graphic3d_Vec2d anOrigXY;
5956     Standard_Real aRadiusStep;
5957     Standard_Integer aDivisionNumber;
5958     Standard_Real aRotAngle = 0.0;
5959     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5960     if (hasOrigin)
5961     {
5962       anOrigXY = aNewOriginXY;
5963     }
5964     if (hasStep)
5965     {
5966       aRadiusStep     = aNewStepXY[0];
5967       aDivisionNumber = (int )aNewStepXY[1];
5968       if (aDivisionNumber < 1)
5969       {
5970         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
5971         return 1;
5972       }
5973     }
5974     if (hasRotAngle)
5975     {
5976       aRotAngle = aNewRotAngle;
5977     }
5978
5979     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5980     if (hasSize || hasZOffset)
5981     {
5982       Standard_Real aRadius = 0.0, aZOffset = 0.0;
5983       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
5984       if (hasSize)
5985       {
5986         aRadius = aNewSizeXY.x();
5987         if (aNewSizeXY.y() != 0.0)
5988         {
5989           std::cout << "Syntax error: circular size should be specified as radius\n";
5990           return 1;
5991         }
5992       }
5993       if (hasZOffset)
5994       {
5995         aZOffset = aNewZOffset;
5996       }
5997       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
5998     }
5999   }
6000   aViewer->ActivateGrid (aType, aMode);
6001   return 0;
6002 }
6003
6004 //==============================================================================
6005 //function : VPriviledgedPlane
6006 //purpose  :
6007 //==============================================================================
6008
6009 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6010                               Standard_Integer  theArgNb,
6011                               const char**      theArgVec)
6012 {
6013   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6014   {
6015     std::cerr << "Error: wrong number of arguments! See usage:\n";
6016     theDI.PrintHelp (theArgVec[0]);
6017     return 1;
6018   }
6019
6020   // get the active viewer
6021   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6022   if (aViewer.IsNull())
6023   {
6024     std::cerr << "Error: no active viewer. Please call vinit.\n";
6025     return 1;
6026   }
6027
6028   if (theArgNb == 1)
6029   {
6030     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6031     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6032     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6033     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6034     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6035           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6036           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6037     return 0;
6038   }
6039
6040   Standard_Integer anArgIdx = 1;
6041   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6042   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6043   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6044   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6045   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6046   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6047
6048   gp_Ax3 aPriviledgedPlane;
6049   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6050   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6051   if (theArgNb > 7)
6052   {
6053     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6054     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6055     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6056     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6057     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6058   }
6059   else
6060   {
6061     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6062   }
6063
6064   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6065
6066   return 0;
6067 }
6068
6069 //==============================================================================
6070 //function : VConvert
6071 //purpose  :
6072 //==============================================================================
6073
6074 static int VConvert (Draw_Interpretor& theDI,
6075                      Standard_Integer  theArgNb,
6076                      const char**      theArgVec)
6077 {
6078   // get the active view
6079   Handle(V3d_View) aView = ViewerTest::CurrentView();
6080   if (aView.IsNull())
6081   {
6082     std::cerr << "Error: no active view. Please call vinit.\n";
6083     return 1;
6084   }
6085
6086   enum { Model, Ray, View, Window, Grid } aMode = Model;
6087
6088   // access coordinate arguments
6089   TColStd_SequenceOfReal aCoord;
6090   Standard_Integer anArgIdx = 1;
6091   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6092   {
6093     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6094     if (!anArg.IsRealValue())
6095     {
6096       break;
6097     }
6098     aCoord.Append (anArg.RealValue());
6099   }
6100
6101   // non-numeric argument too early
6102   if (aCoord.IsEmpty())
6103   {
6104     std::cerr << "Error: wrong number of arguments! See usage:\n";
6105     theDI.PrintHelp (theArgVec[0]);
6106     return 1;
6107   }
6108
6109   // collect all other arguments and options
6110   for (; anArgIdx < theArgNb; ++anArgIdx)
6111   {
6112     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6113     anArg.LowerCase();
6114     if      (anArg == "window") aMode = Window;
6115     else if (anArg == "view")   aMode = View;
6116     else if (anArg == "grid")   aMode = Grid;
6117     else if (anArg == "ray")    aMode = Ray;
6118     else
6119     {
6120       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6121       theDI.PrintHelp (theArgVec[0]);
6122       return 1;
6123     }
6124   }
6125
6126   // complete input checks
6127   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6128       (aCoord.Length() == 2 && theArgNb > 4) ||
6129       (aCoord.Length() == 3 && theArgNb > 5))
6130   {
6131     std::cerr << "Error: wrong number of arguments! See usage:\n";
6132     theDI.PrintHelp (theArgVec[0]);
6133     return 1;
6134   }
6135
6136   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6137   Standard_Integer aXYp[2] = {0, 0};
6138
6139   // convert one-dimensional coordinate
6140   if (aCoord.Length() == 1)
6141   {
6142     switch (aMode)
6143     {
6144       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6145       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6146       default:
6147         std::cerr << "Error: wrong arguments! See usage:\n";
6148         theDI.PrintHelp (theArgVec[0]);
6149         return 1;
6150     }
6151   }
6152
6153   // convert 2D coordinates from projection or view reference space
6154   if (aCoord.Length() == 2)
6155   {
6156     switch (aMode)
6157     {
6158       case Model :
6159         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6160         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6161         return 0;
6162
6163       case View :
6164         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6165         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6166         return 0;
6167
6168       case Window :
6169         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6170         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6171         return 0;
6172
6173       case Grid :
6174         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6175         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6176         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6177         return 0;
6178
6179       case Ray :
6180         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6181                                 (Standard_Integer) aCoord (2),
6182                                 aXYZ[0], aXYZ[1], aXYZ[2],
6183                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6184         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6185         return 0;
6186
6187       default:
6188         std::cerr << "Error: wrong arguments! See usage:\n";
6189         theDI.PrintHelp (theArgVec[0]);
6190         return 1;
6191     }
6192   }
6193
6194   // convert 3D coordinates from view reference space
6195   else if (aCoord.Length() == 3)
6196   {
6197     switch (aMode)
6198     {
6199       case Window :
6200         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6201         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6202         return 0;
6203
6204       case Grid :
6205         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6206         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6207         return 0;
6208
6209       default:
6210         std::cerr << "Error: wrong arguments! See usage:\n";
6211         theDI.PrintHelp (theArgVec[0]);
6212         return 1;
6213     }
6214   }
6215
6216   return 0;
6217 }
6218
6219 //==============================================================================
6220 //function : VFps
6221 //purpose  :
6222 //==============================================================================
6223
6224 static int VFps (Draw_Interpretor& theDI,
6225                  Standard_Integer  theArgNb,
6226                  const char**      theArgVec)
6227 {
6228   // get the active view
6229   Handle(V3d_View) aView = ViewerTest::CurrentView();
6230   if (aView.IsNull())
6231   {
6232     std::cerr << "No active view. Please call vinit.\n";
6233     return 1;
6234   }
6235
6236   Standard_Integer aFramesNb = -1;
6237   Standard_Real aDuration = -1.0;
6238   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6239   {
6240     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6241     anArg.LowerCase();
6242     if (aDuration < 0.0
6243      && anArgIter + 1 < theArgNb
6244      && (anArg == "-duration"
6245       || anArg == "-dur"
6246       || anArg == "-time"))
6247     {
6248       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6249     }
6250     else if (aFramesNb < 0
6251           && anArg.IsIntegerValue())
6252     {
6253       aFramesNb = anArg.IntegerValue();
6254       if (aFramesNb <= 0)
6255       {
6256         std::cerr << "Syntax error at '" << anArg << "'\n";
6257         return 1;
6258       }
6259     }
6260     else
6261     {
6262       std::cerr << "Syntax error at '" << anArg << "'\n";
6263       return 1;
6264     }
6265   }
6266   if (aFramesNb < 0 && aDuration < 0.0)
6267   {
6268     aFramesNb = 100;
6269   }
6270
6271   // the time is meaningless for first call
6272   // due to async OpenGl rendering
6273   aView->Redraw();
6274
6275   // redraw view in loop to estimate average values
6276   OSD_Timer aTimer;
6277   aTimer.Start();
6278   Standard_Integer aFrameIter = 1;
6279   for (;; ++aFrameIter)
6280   {
6281     aView->Redraw();
6282     if ((aFramesNb > 0
6283       && aFrameIter >= aFramesNb)
6284      || (aDuration > 0.0
6285       && aTimer.ElapsedTime() >= aDuration))
6286     {
6287       break;
6288     }
6289   }
6290   aTimer.Stop();
6291   Standard_Real aCpu;
6292   const Standard_Real aTime = aTimer.ElapsedTime();
6293   aTimer.OSD_Chronometer::Show (aCpu);
6294
6295   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6296   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6297
6298   // return statistics
6299   theDI << "FPS: " << aFpsAver << "\n"
6300         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6301
6302   // compute additional statistics in ray-tracing mode
6303   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6304   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6305   {
6306     Graphic3d_Vec2i aWinSize (0, 0);
6307     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6308
6309     // 1 shadow ray and 1 secondary ray pew each bounce
6310     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6311     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6312   }
6313
6314   return 0;
6315 }
6316
6317 //! Auxiliary function for parsing glsl dump level argument.
6318 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6319                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6320 {
6321   TCollection_AsciiString aTypeStr (theArg);
6322   aTypeStr.LowerCase();
6323   if (aTypeStr == "off"
6324    || aTypeStr == "0")
6325   {
6326     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6327   }
6328   else if (aTypeStr == "short")
6329   {
6330     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6331   }
6332   else if (aTypeStr == "full"
6333         || aTypeStr == "1")
6334   {
6335     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6336   }
6337   else
6338   {
6339     return Standard_False;
6340   }
6341   return Standard_True;
6342 }
6343
6344 //==============================================================================
6345 //function : VGlDebug
6346 //purpose  :
6347 //==============================================================================
6348
6349 static int VGlDebug (Draw_Interpretor& theDI,
6350                      Standard_Integer  theArgNb,
6351                      const char**      theArgVec)
6352 {
6353   Handle(OpenGl_GraphicDriver) aDriver;
6354   Handle(V3d_View) aView = ViewerTest::CurrentView();
6355   if (!aView.IsNull())
6356   {
6357     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6358   }
6359   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6360   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6361
6362   if (theArgNb < 2)
6363   {
6364     TCollection_AsciiString aDebActive, aSyncActive;
6365     if (aCaps == NULL)
6366     {
6367       aCaps = aDefCaps;
6368     }
6369     else
6370     {
6371       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6372                                                                   "GL_ARB_debug_output");
6373       aDebActive = isActive ? " (active)" : " (inactive)";
6374       if (isActive)
6375       {
6376         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6377         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6378       }
6379     }
6380
6381     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6382       + "glslSourceCode: "
6383       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6384          ? "Off"
6385          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6386           ? "Short"
6387           : "Full")
6388       + "\n";
6389     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6390           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6391           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6392           << aGlslCodeDebugStatus
6393           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6394     return 0;
6395   }
6396
6397   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6398   {
6399     Standard_CString        anArg     = theArgVec[anArgIter];
6400     TCollection_AsciiString anArgCase (anArg);
6401     anArgCase.LowerCase();
6402     Standard_Boolean toEnableDebug = Standard_True;
6403     if (anArgCase == "-glsl"
6404      || anArgCase == "-glslwarn"
6405      || anArgCase == "-glslwarns"
6406      || anArgCase == "-glslwarnings")
6407     {
6408       Standard_Boolean toShowWarns = Standard_True;
6409       if (++anArgIter < theArgNb
6410       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6411       {
6412         --anArgIter;
6413       }
6414       aDefCaps->glslWarnings = toShowWarns;
6415       if (aCaps != NULL)
6416       {
6417         aCaps->glslWarnings = toShowWarns;
6418       }
6419     }
6420     else if (anArgCase == "-extra"
6421           || anArgCase == "-extramsg"
6422           || anArgCase == "-extramessages")
6423     {
6424       Standard_Boolean toShow = Standard_True;
6425       if (++anArgIter < theArgNb
6426       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6427       {
6428         --anArgIter;
6429       }
6430       aDefCaps->suppressExtraMsg = !toShow;
6431       if (aCaps != NULL)
6432       {
6433         aCaps->suppressExtraMsg = !toShow;
6434       }
6435     }
6436     else if (anArgCase == "-noextra"
6437           || anArgCase == "-noextramsg"
6438           || anArgCase == "-noextramessages")
6439     {
6440       Standard_Boolean toSuppress = Standard_True;
6441       if (++anArgIter < theArgNb
6442       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6443       {
6444         --anArgIter;
6445       }
6446       aDefCaps->suppressExtraMsg = toSuppress;
6447       if (aCaps != NULL)
6448       {
6449         aCaps->suppressExtraMsg = toSuppress;
6450       }
6451     }
6452     else if (anArgCase == "-sync")
6453     {
6454       Standard_Boolean toSync = Standard_True;
6455       if (++anArgIter < theArgNb
6456       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6457       {
6458         --anArgIter;
6459       }
6460       aDefCaps->contextSyncDebug = toSync;
6461       if (toSync)
6462       {
6463         aDefCaps->contextDebug = Standard_True;
6464       }
6465     }
6466     else if (anArgCase == "-glslsourcecode"
6467           || anArgCase == "-glslcode")
6468     {
6469       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6470       if (++anArgIter < theArgNb
6471       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6472       {
6473         --anArgIter;
6474       }
6475       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6476       if (aCaps != NULL)
6477       {
6478         aCaps->glslDumpLevel = aGslsDumpLevel;
6479       }
6480     }
6481     else if (anArgCase == "-debug")
6482     {
6483       if (++anArgIter < theArgNb
6484       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6485       {
6486         --anArgIter;
6487       }
6488       aDefCaps->contextDebug = toEnableDebug;
6489     }
6490     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6491           && (anArgIter + 1 == theArgNb))
6492     {
6493       // simple alias to turn on almost everything
6494       aDefCaps->contextDebug     = toEnableDebug;
6495       aDefCaps->contextSyncDebug = toEnableDebug;
6496       aDefCaps->glslWarnings     = toEnableDebug;
6497       if (!toEnableDebug)
6498       {
6499         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6500       }
6501       aDefCaps->suppressExtraMsg = !toEnableDebug;
6502       if (aCaps != NULL)
6503       {
6504         aCaps->contextDebug     = toEnableDebug;
6505         aCaps->contextSyncDebug = toEnableDebug;
6506         aCaps->glslWarnings     = toEnableDebug;
6507         if (!toEnableDebug)
6508         {
6509           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6510         }
6511         aCaps->suppressExtraMsg = !toEnableDebug;
6512       }
6513     }
6514     else
6515     {
6516       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6517       return 1;
6518     }
6519   }
6520
6521   return 0;
6522 }
6523
6524 //==============================================================================
6525 //function : VVbo
6526 //purpose  :
6527 //==============================================================================
6528
6529 static int VVbo (Draw_Interpretor& theDI,
6530                  Standard_Integer  theArgNb,
6531                  const char**      theArgVec)
6532 {
6533   const Standard_Boolean toSet    = (theArgNb > 1);
6534   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6535   if (toSet)
6536   {
6537     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6538   }
6539
6540   // get the context
6541   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6542   if (aContextAIS.IsNull())
6543   {
6544     if (!toSet)
6545     {
6546       std::cerr << "No active view!\n";
6547     }
6548     return 1;
6549   }
6550   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6551   if (!aDriver.IsNull())
6552   {
6553     if (!toSet)
6554     {
6555       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6556     }
6557     else
6558     {
6559       aDriver->ChangeOptions().vboDisable = toUseVbo;
6560     }
6561   }
6562
6563   return 0;
6564 }
6565
6566 //==============================================================================
6567 //function : VCaps
6568 //purpose  :
6569 //==============================================================================
6570
6571 static int VCaps (Draw_Interpretor& theDI,
6572                   Standard_Integer  theArgNb,
6573                   const char**      theArgVec)
6574 {
6575   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6576   Handle(OpenGl_GraphicDriver)   aDriver;
6577   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6578   if (!aContext.IsNull())
6579   {
6580     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6581     aCaps   = &aDriver->ChangeOptions();
6582   }
6583
6584   if (theArgNb < 2)
6585   {
6586     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6587     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6588     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6589     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6590     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6591     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6592     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6593     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6594     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6595     return 0;
6596   }
6597
6598   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6599   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6600   {
6601     Standard_CString        anArg     = theArgVec[anArgIter];
6602     TCollection_AsciiString anArgCase (anArg);
6603     anArgCase.LowerCase();
6604     if (anUpdateTool.parseRedrawMode (anArg))
6605     {
6606       continue;
6607     }
6608     else if (anArgCase == "-vsync"
6609           || anArgCase == "-swapinterval")
6610     {
6611       Standard_Boolean toEnable = Standard_True;
6612       if (++anArgIter < theArgNb
6613       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6614       {
6615         --anArgIter;
6616       }
6617       aCaps->swapInterval = toEnable;
6618     }
6619     else if (anArgCase == "-ffp")
6620     {
6621       Standard_Boolean toEnable = Standard_True;
6622       if (++anArgIter < theArgNb
6623       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6624       {
6625         --anArgIter;
6626       }
6627       aCaps->ffpEnable = toEnable;
6628     }
6629     else if (anArgCase == "-polygonmode")
6630     {
6631       Standard_Boolean toEnable = Standard_True;
6632       if (++anArgIter < theArgNb
6633       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6634       {
6635         --anArgIter;
6636       }
6637       aCaps->usePolygonMode = toEnable;
6638     }
6639     else if (anArgCase == "-vbo")
6640     {
6641       Standard_Boolean toEnable = Standard_True;
6642       if (++anArgIter < theArgNb
6643       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6644       {
6645         --anArgIter;
6646       }
6647       aCaps->vboDisable = !toEnable;
6648     }
6649     else if (anArgCase == "-sprite"
6650           || anArgCase == "-sprites")
6651     {
6652       Standard_Boolean toEnable = Standard_True;
6653       if (++anArgIter < theArgNb
6654       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6655       {
6656         --anArgIter;
6657       }
6658       aCaps->pntSpritesDisable = !toEnable;
6659     }
6660     else if (anArgCase == "-softmode")
6661     {
6662       Standard_Boolean toEnable = Standard_True;
6663       if (++anArgIter < theArgNb
6664       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6665       {
6666         --anArgIter;
6667       }
6668       aCaps->contextNoAccel = toEnable;
6669     }
6670     else if (anArgCase == "-winbuffer"
6671           || anArgCase == "-windowbuffer"
6672           || anArgCase == "-usewinbuffer"
6673           || anArgCase == "-usewindowbuffer"
6674           || anArgCase == "-usesystembuffer")
6675     {
6676       Standard_Boolean toEnable = Standard_True;
6677       if (++anArgIter < theArgNb
6678       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6679       {
6680         --anArgIter;
6681       }
6682       aCaps->useSystemBuffer = toEnable;
6683     }
6684     else if (anArgCase == "-accel"
6685           || anArgCase == "-acceleration")
6686     {
6687       Standard_Boolean toEnable = Standard_True;
6688       if (++anArgIter < theArgNb
6689       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6690       {
6691         --anArgIter;
6692       }
6693       aCaps->contextNoAccel = !toEnable;
6694     }
6695     else if (anArgCase == "-compat"
6696           || anArgCase == "-compatprofile"
6697           || anArgCase == "-compatible"
6698           || anArgCase == "-compatibleprofile")
6699     {
6700       Standard_Boolean toEnable = Standard_True;
6701       if (++anArgIter < theArgNb
6702       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6703       {
6704         --anArgIter;
6705       }
6706       aCaps->contextCompatible = toEnable;
6707       if (!aCaps->contextCompatible)
6708       {
6709         aCaps->ffpEnable = Standard_False;
6710       }
6711     }
6712     else if (anArgCase == "-core"
6713           || anArgCase == "-coreprofile")
6714     {
6715       Standard_Boolean toEnable = Standard_True;
6716       if (++anArgIter < theArgNb
6717       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6718       {
6719         --anArgIter;
6720       }
6721       aCaps->contextCompatible = !toEnable;
6722       if (!aCaps->contextCompatible)
6723       {
6724         aCaps->ffpEnable = Standard_False;
6725       }
6726     }
6727     else if (anArgCase == "-stereo"
6728           || anArgCase == "-quadbuffer")
6729     {
6730       Standard_Boolean toEnable = Standard_True;
6731       if (++anArgIter < theArgNb
6732       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6733       {
6734         --anArgIter;
6735       }
6736       aCaps->contextStereo = toEnable;
6737     }
6738     else
6739     {
6740       std::cout << "Error: unknown argument '" << anArg << "'\n";
6741       return 1;
6742     }
6743   }
6744   if (aCaps != &ViewerTest_myDefaultCaps)
6745   {
6746     ViewerTest_myDefaultCaps = *aCaps;
6747   }
6748   return 0;
6749 }
6750
6751 //==============================================================================
6752 //function : VMemGpu
6753 //purpose  :
6754 //==============================================================================
6755
6756 static int VMemGpu (Draw_Interpretor& theDI,
6757                     Standard_Integer  theArgNb,
6758                     const char**      theArgVec)
6759 {
6760   // get the context
6761   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6762   if (aContextAIS.IsNull())
6763   {
6764     std::cerr << "No active view. Please call vinit.\n";
6765     return 1;
6766   }
6767
6768   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6769   if (aDriver.IsNull())
6770   {
6771     std::cerr << "Graphic driver not available.\n";
6772     return 1;
6773   }
6774
6775   Standard_Size aFreeBytes = 0;
6776   TCollection_AsciiString anInfo;
6777   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6778   {
6779     std::cerr << "Information not available.\n";
6780     return 1;
6781   }
6782
6783   if (theArgNb > 1 && *theArgVec[1] == 'f')
6784   {
6785     theDI << Standard_Real (aFreeBytes);
6786   }
6787   else
6788   {
6789     theDI << anInfo;
6790   }
6791
6792   return 0;
6793 }
6794
6795 // ==============================================================================
6796 // function : VReadPixel
6797 // purpose  :
6798 // ==============================================================================
6799 static int VReadPixel (Draw_Interpretor& theDI,
6800                        Standard_Integer  theArgNb,
6801                        const char**      theArgVec)
6802 {
6803   // get the active view
6804   Handle(V3d_View) aView = ViewerTest::CurrentView();
6805   if (aView.IsNull())
6806   {
6807     std::cerr << "No active view. Please call vinit.\n";
6808     return 1;
6809   }
6810   else if (theArgNb < 3)
6811   {
6812     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6813     return 1;
6814   }
6815
6816   Image_Format         aFormat     = Image_Format_RGBA;
6817   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6818
6819   Standard_Integer aWidth, aHeight;
6820   aView->Window()->Size (aWidth, aHeight);
6821   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6822   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6823   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6824   {
6825     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6826     return 1;
6827   }
6828
6829   Standard_Boolean toShowName = Standard_False;
6830   Standard_Boolean toShowHls  = Standard_False;
6831   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6832   {
6833     TCollection_AsciiString aParam (theArgVec[anIter]);
6834     aParam.LowerCase();
6835     if (aParam == "-rgb"
6836      || aParam == "rgb")
6837     {
6838       aFormat     = Image_Format_RGB;
6839       aBufferType = Graphic3d_BT_RGB;
6840     }
6841     else if (aParam == "-hls"
6842           || aParam == "hls")
6843     {
6844       aFormat     = Image_Format_RGB;
6845       aBufferType = Graphic3d_BT_RGB;
6846       toShowHls   = Standard_True;
6847     }
6848     else if (aParam == "-rgbf"
6849           || aParam == "rgbf")
6850     {
6851       aFormat     = Image_Format_RGBF;
6852       aBufferType = Graphic3d_BT_RGB;
6853     }
6854     else if (aParam == "-rgba"
6855           || aParam == "rgba")
6856     {
6857       aFormat     = Image_Format_RGBA;
6858       aBufferType = Graphic3d_BT_RGBA;
6859     }
6860     else if (aParam == "-rgbaf"
6861           || aParam == "rgbaf")
6862     {
6863       aFormat     = Image_Format_RGBAF;
6864       aBufferType = Graphic3d_BT_RGBA;
6865     }
6866     else if (aParam == "-depth"
6867           || aParam == "depth")
6868     {
6869       aFormat     = Image_Format_GrayF;
6870       aBufferType = Graphic3d_BT_Depth;
6871     }
6872     else if (aParam == "-name"
6873           || aParam == "name")
6874     {
6875       toShowName = Standard_True;
6876     }
6877     else
6878     {
6879       std::cout << "Syntax error at '" << aParam << "'\n";
6880     }
6881   }
6882
6883   Image_PixMap anImage;
6884   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6885   {
6886     std::cerr << "Image allocation failed\n";
6887     return 1;
6888   }
6889   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6890   {
6891     std::cerr << "Image dump failed\n";
6892     return 1;
6893   }
6894
6895   // redirect possible warning messages that could have been added by ToPixMap
6896   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6897   // contaminate result of the command
6898   Standard_CString aWarnLog = theDI.Result();
6899   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6900   {
6901     std::cout << aWarnLog << std::endl;
6902   }
6903   theDI.Reset();
6904
6905   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6906   if (toShowName)
6907   {
6908     if (aBufferType == Graphic3d_BT_RGBA)
6909     {
6910       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6911     }
6912     else
6913     {
6914       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6915     }
6916   }
6917   else
6918   {
6919     switch (aBufferType)
6920     {
6921       default:
6922       case Graphic3d_BT_RGB:
6923       {
6924         if (toShowHls)
6925         {
6926           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6927         }
6928         else
6929         {
6930           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6931         }
6932         break;
6933       }
6934       case Graphic3d_BT_RGBA:
6935       {
6936         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6937         break;
6938       }
6939       case Graphic3d_BT_Depth:
6940       {
6941         theDI << aColor.GetRGB().Red();
6942         break;
6943       }
6944     }
6945   }
6946
6947   return 0;
6948 }
6949
6950 //! Auxiliary presentation for an image plane.
6951 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6952 {
6953 public:
6954   //! Main constructor.
6955   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6956                        const Standard_Real theWidth,
6957                        const Standard_Real theHeight,
6958                        const TCollection_AsciiString& theLabel)
6959   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6960   {
6961     SetDisplayMode (0);
6962     SetHilightMode (1);
6963     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6964     {
6965       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6966       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
6967       Graphic3d_MaterialAspect aMat;
6968       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
6969       aMat.SetAmbient  (1.0);
6970       aMat.SetDiffuse  (1.0);
6971       aMat.SetSpecular (1.0);
6972       aMat.SetEmissive (1.0);
6973       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
6974       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
6975       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
6976       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
6977       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6978       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
6979       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6980       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
6981       aFillAspect->SetFrontMaterial (aMat);
6982       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
6983       aFillAspect->SetTextureMapOn();
6984     }
6985     {
6986       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
6987       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
6988       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
6989       myDrawer->SetTextAspect (aTextAspect);
6990     }
6991     {
6992       const gp_Dir aNorm (0.0, 0.0, 1.0);
6993       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
6994       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
6995       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
6996       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
6997       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
6998       myTris->AddEdge (1);
6999       myTris->AddEdge (2);
7000       myTris->AddEdge (3);
7001       myTris->AddEdge (3);
7002       myTris->AddEdge (2);
7003       myTris->AddEdge (4);
7004
7005       myRect = new Graphic3d_ArrayOfPolylines (4);
7006       myRect->AddVertex (myTris->Vertice (1));
7007       myRect->AddVertex (myTris->Vertice (3));
7008       myRect->AddVertex (myTris->Vertice (4));
7009       myRect->AddVertex (myTris->Vertice (2));
7010     }
7011   }
7012
7013   //! Returns TRUE for accepted display modes.
7014   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7015
7016   //! Compute presentation.
7017   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7018   {
7019     switch (theMode)
7020     {
7021       case 0:
7022       {
7023         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7024         aGroup->AddPrimitiveArray (myTris);
7025         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7026         aGroup->AddPrimitiveArray (myRect);
7027         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7028         return;
7029       }
7030       case 1:
7031       {
7032         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7033         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7034         aGroup->AddPrimitiveArray (myRect);
7035         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7036         return;
7037       }
7038     }
7039   }
7040
7041   //! Compute selection.
7042   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7043   {
7044     if (theMode == 0)
7045     {
7046       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7047       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7048       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7049       theSel->Add (aSensitive);
7050     }
7051   }
7052
7053 private:
7054   Handle(Graphic3d_ArrayOfTriangles) myTris;
7055   Handle(Graphic3d_ArrayOfPolylines) myRect;
7056   TCollection_AsciiString myLabel;
7057   Standard_Real myWidth;
7058   Standard_Real myHeight;
7059 };
7060
7061 //==============================================================================
7062 //function : VDiffImage
7063 //purpose  : The draw-command compares two images.
7064 //==============================================================================
7065
7066 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7067 {
7068   if (theArgNb < 3)
7069   {
7070     std::cout << "Syntax error: not enough arguments.\n";
7071     return 1;
7072   }
7073
7074   Standard_Integer anArgIter = 1;
7075   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7076   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7077   TCollection_AsciiString aDiffImagePath;
7078   Standard_Real    aTolColor        = -1.0;
7079   Standard_Integer toBlackWhite     = -1;
7080   Standard_Integer isBorderFilterOn = -1;
7081   Standard_Boolean isOldSyntax = Standard_False;
7082   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7083   for (; anArgIter < theArgNb; ++anArgIter)
7084   {
7085     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7086     anArg.LowerCase();
7087     if (anArgIter + 1 < theArgNb
7088      && (anArg == "-toleranceofcolor"
7089       || anArg == "-tolerancecolor"
7090       || anArg == "-tolerance"
7091       || anArg == "-toler"))
7092     {
7093       aTolColor = Atof (theArgVec[++anArgIter]);
7094       if (aTolColor < 0.0 || aTolColor > 1.0)
7095       {
7096         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7097         return 1;
7098       }
7099     }
7100     else if (anArg == "-blackwhite")
7101     {
7102       Standard_Boolean toEnable = Standard_True;
7103       if (anArgIter + 1 < theArgNb
7104        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7105       {
7106         ++anArgIter;
7107       }
7108       toBlackWhite = toEnable ? 1 : 0;
7109     }
7110     else if (anArg == "-borderfilter")
7111     {
7112       Standard_Boolean toEnable = Standard_True;
7113       if (anArgIter + 1 < theArgNb
7114        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7115       {
7116         ++anArgIter;
7117       }
7118       isBorderFilterOn = toEnable ? 1 : 0;
7119     }
7120     else if (anArg == "-exitonclose")
7121     {
7122       ViewerTest_EventManager::ToExitOnCloseView() = true;
7123       if (anArgIter + 1 < theArgNb
7124        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7125       {
7126         ++anArgIter;
7127       }
7128     }
7129     else if (anArg == "-closeonescape"
7130           || anArg == "-closeonesc")
7131     {
7132       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7133       if (anArgIter + 1 < theArgNb
7134        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7135       {
7136         ++anArgIter;
7137       }
7138     }
7139     else if (anArgIter + 3 < theArgNb
7140           && anArg == "-display")
7141     {
7142       aViewName   = theArgVec[++anArgIter];
7143       aPrsNameRef = theArgVec[++anArgIter];
7144       aPrsNameNew = theArgVec[++anArgIter];
7145       if (anArgIter + 1 < theArgNb
7146       && *theArgVec[anArgIter + 1] != '-')
7147       {
7148         aPrsNameDiff = theArgVec[++anArgIter];
7149       }
7150     }
7151     else if (aTolColor < 0.0
7152           && anArg.IsRealValue())
7153     {
7154       isOldSyntax = Standard_True;
7155       aTolColor = anArg.RealValue();
7156       if (aTolColor < 0.0 || aTolColor > 1.0)
7157       {
7158         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7159         return 1;
7160       }
7161     }
7162     else if (isOldSyntax
7163           && toBlackWhite == -1
7164           && (anArg == "0" || anArg == "1"))
7165     {
7166       toBlackWhite = anArg == "1" ? 1 : 0;
7167     }
7168     else if (isOldSyntax
7169           && isBorderFilterOn == -1
7170           && (anArg == "0" || anArg == "1"))
7171     {
7172       isBorderFilterOn = anArg == "1" ? 1 : 0;
7173     }
7174     else if (aDiffImagePath.IsEmpty())
7175     {
7176       aDiffImagePath = theArgVec[anArgIter];
7177     }
7178     else
7179     {
7180       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7181       return 1;
7182     }
7183   }
7184
7185   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7186   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7187   if (!anImgRef->Load (anImgPathRef))
7188   {
7189     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7190     return 1;
7191   }
7192   if (!anImgNew->Load (anImgPathNew))
7193   {
7194     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7195     return 1;
7196   }
7197
7198   // compare the images
7199   Image_Diff aComparer;
7200   Standard_Integer aDiffColorsNb = -1;
7201   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7202   {
7203     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7204     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7205     aDiffColorsNb = aComparer.Compare();
7206     theDI << aDiffColorsNb << "\n";
7207   }
7208
7209   // save image of difference
7210   Handle(Image_AlienPixMap) aDiff;
7211   if (aDiffColorsNb > 0
7212   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7213   {
7214     aDiff = new Image_AlienPixMap();
7215     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7216     {
7217       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7218       return 1;
7219     }
7220     aComparer.SaveDiffImage (*aDiff);
7221     if (!aDiffImagePath.IsEmpty()
7222      && !aDiff->Save (aDiffImagePath))
7223     {
7224       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7225       return 1;
7226     }
7227   }
7228
7229   if (aViewName.IsEmpty())
7230   {
7231     return 0;
7232   }
7233
7234   ViewerTest_Names aViewNames (aViewName);
7235   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7236   {
7237     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7238     theDI.Eval (aCommand.ToCString());
7239   }
7240
7241   Standard_Integer aPxLeft = 0;
7242   Standard_Integer aPxTop  = 0;
7243   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7244   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7245                               ? int(anImgRef->SizeY() * 2)
7246                               : int(anImgRef->SizeY());
7247   TCollection_AsciiString aDisplayName;
7248   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7249                                                             aViewName, aDisplayName);
7250
7251   Standard_Real aRatio = anImgRef->Ratio();
7252   Standard_Real aSizeX = 1.0;
7253   Standard_Real aSizeY = aSizeX / aRatio;
7254   {
7255     OSD_Path aPath (anImgPathRef);
7256     TCollection_AsciiString aLabelRef;
7257     if (!aPath.Name().IsEmpty())
7258     {
7259       aLabelRef = aPath.Name() + aPath.Extension();
7260     }
7261     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7262
7263     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7264     gp_Trsf aTrsfRef;
7265     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7266     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7267     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7268   }
7269   {
7270     OSD_Path aPath (anImgPathNew);
7271     TCollection_AsciiString aLabelNew;
7272     if (!aPath.Name().IsEmpty())
7273     {
7274       aLabelNew = aPath.Name() + aPath.Extension();
7275     }
7276     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7277
7278     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7279     gp_Trsf aTrsfRef;
7280     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7281     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7282     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7283   }
7284   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7285   if (!aDiff.IsNull())
7286   {
7287     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7288     gp_Trsf aTrsfDiff;
7289     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7290     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7291   }
7292   if (!aPrsNameDiff.IsEmpty())
7293   {
7294     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7295   }
7296   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7297   ViewerTest::CurrentView()->FitAll();
7298   return 0;
7299 }
7300
7301 //=======================================================================
7302 //function : VSelect
7303 //purpose  : Emulates different types of selection by mouse:
7304 //           1) single click selection
7305 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7306 //           3) selection with polygon having corners at
7307 //           pixel positions (x1,y1),...,(xn,yn)
7308 //           4) any of these selections with shift button pressed
7309 //=======================================================================
7310 static Standard_Integer VSelect (Draw_Interpretor& ,
7311                                  Standard_Integer theNbArgs,
7312                                  const char** theArgVec)
7313 {
7314   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7315   if (aCtx.IsNull())
7316   {
7317     std::cout << "Error: no active View\n";
7318     return 1;
7319   }
7320
7321   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7322   bool isShiftSelection = false, toAllowOverlap = false;
7323   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7324   {
7325     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7326     anArg.LowerCase();
7327     if (anArg == "-allowoverlap")
7328     {
7329       toAllowOverlap = true;
7330       if (anArgIter + 1 < theNbArgs
7331        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7332       {
7333         ++anArgIter;
7334       }
7335     }
7336     else if (anArgIter + 1 < theNbArgs
7337           && anArg.IsIntegerValue()
7338           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7339     {
7340       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7341       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7342     }
7343     else if (anArgIter + 1 == theNbArgs
7344           && anArg.IsIntegerValue())
7345     {
7346       isShiftSelection = anArg.IntegerValue() == 1;
7347     }
7348     else
7349     {
7350       std::cout << "Syntax error at '" << anArg << "'\n";
7351       return 1;
7352     }
7353   }
7354   if (toAllowOverlap
7355    && aPnts.Length() != 2)
7356   {
7357     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7358     return 1;
7359   }
7360   if (toAllowOverlap)
7361   {
7362     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7363   }
7364
7365   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7366   if (aPnts.IsEmpty())
7367   {
7368     if (isShiftSelection)
7369     {
7370       aCtx->ShiftSelect (false);
7371     }
7372     else
7373     {
7374       aCtx->Select (false);
7375     }
7376     aCtx->CurrentViewer()->Invalidate();
7377   }
7378   else if (aPnts.Length() == 2)
7379   {
7380     if (toAllowOverlap
7381      && aPnts.First().y() < aPnts.Last().y())
7382     {
7383       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7384     }
7385     else if (!toAllowOverlap
7386            && aPnts.First().y() > aPnts.Last().y())
7387     {
7388       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7389     }
7390     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7391   }
7392   else
7393   {
7394     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7395   }
7396   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7397   return 0;
7398 }
7399
7400 //=======================================================================
7401 //function : VMoveTo
7402 //purpose  : Emulates cursor movement to defined pixel position
7403 //=======================================================================
7404 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7405                                 Standard_Integer theNbArgs,
7406                                 const char**     theArgVec)
7407 {
7408   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7409   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7410   if (aContext.IsNull())
7411   {
7412     std::cout << "Error: no active View\n";
7413     return 1;
7414   }
7415
7416   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7417   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7418   {
7419     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7420     anArgStr.LowerCase();
7421     if (anArgStr == "-reset"
7422      || anArgStr == "-clear")
7423     {
7424       if (anArgIter + 1 < theNbArgs)
7425       {
7426         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7427         return 1;
7428       }
7429
7430       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7431                                        && aContext->CurrentViewer()->GridEcho();
7432       if (toEchoGrid)
7433       {
7434         aContext->CurrentViewer()->HideGridEcho (aView);
7435       }
7436       if (aContext->ClearDetected() || toEchoGrid)
7437       {
7438         aContext->CurrentViewer()->RedrawImmediate();
7439       }
7440       return 0;
7441     }
7442     else if (aMousePos.x() == IntegerLast()
7443           && anArgStr.IsIntegerValue())
7444     {
7445       aMousePos.x() = anArgStr.IntegerValue();
7446     }
7447     else if (aMousePos.y() == IntegerLast()
7448           && anArgStr.IsIntegerValue())
7449     {
7450       aMousePos.y() = anArgStr.IntegerValue();
7451     }
7452     else
7453     {
7454       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7455       return 1;
7456     }
7457   }
7458
7459   if (aMousePos.x() == IntegerLast()
7460    || aMousePos.y() == IntegerLast())
7461   {
7462     std::cout << "Syntax error: wrong number of arguments\n";
7463     return 1;
7464   }
7465
7466   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7467   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7468   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7469
7470   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7471   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7472   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7473   {
7474     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7475     {
7476       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7477       break;
7478     }
7479   }
7480   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7481   return 0;
7482 }
7483
7484 namespace
7485 {
7486   //! Global map storing all animations registered in ViewerTest.
7487   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7488
7489   //! The animation calling the Draw Harness command.
7490   class ViewerTest_AnimationProc : public AIS_Animation
7491   {
7492   public:
7493
7494     //! Main constructor.
7495     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7496                               Draw_Interpretor* theDI,
7497                               const TCollection_AsciiString& theCommand)
7498     : AIS_Animation (theAnimationName),
7499       myDrawInter(theDI),
7500       myCommand  (theCommand)
7501     {
7502       //
7503     }
7504
7505   protected:
7506
7507     //! Evaluate the command.
7508     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7509     {
7510       TCollection_AsciiString aCmd = myCommand;
7511       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7512       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7513       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7514       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7515       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7516       myDrawInter->Eval (aCmd.ToCString());
7517     }
7518
7519     //! Find the keyword in the command and replace it with value.
7520     //! @return the position of the keyword to pass value
7521     void replace (TCollection_AsciiString&       theCmd,
7522                   const TCollection_AsciiString& theKey,
7523                   const TCollection_AsciiString& theVal)
7524     {
7525       TCollection_AsciiString aCmd (theCmd);
7526       aCmd.LowerCase();
7527       const Standard_Integer aPos = aCmd.Search (theKey);
7528       if (aPos == -1)
7529       {
7530         return;
7531       }
7532
7533       TCollection_AsciiString aPart1, aPart2;
7534       Standard_Integer aPart1To = aPos - 1;
7535       if (aPart1To >= 1
7536        && aPart1To <= theCmd.Length())
7537       {
7538         aPart1 = theCmd.SubString (1, aPart1To);
7539       }
7540
7541       Standard_Integer aPart2From = aPos + theKey.Length();
7542       if (aPart2From >= 1
7543        && aPart2From <= theCmd.Length())
7544       {
7545         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7546       }
7547
7548       theCmd = aPart1 + theVal + aPart2;
7549     }
7550
7551   protected:
7552
7553     Draw_Interpretor*       myDrawInter;
7554     TCollection_AsciiString myCommand;
7555
7556   };
7557
7558   //! Replace the animation with the new one.
7559   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7560                                 Handle(AIS_Animation)&       theAnimation,
7561                                 const Handle(AIS_Animation)& theAnimationNew)
7562   {
7563     theAnimationNew->CopyFrom (theAnimation);
7564     if (!theParentAnimation.IsNull())
7565     {
7566       theParentAnimation->Replace (theAnimation, theAnimationNew);
7567     }
7568     else
7569     {
7570       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7571       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7572     }
7573     theAnimation = theAnimationNew;
7574   }
7575
7576   //! Parse the point.
7577   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7578   {
7579     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7580     if (!anXYZ[0].IsRealValue()
7581      || !anXYZ[1].IsRealValue()
7582      || !anXYZ[2].IsRealValue())
7583     {
7584       return Standard_False;
7585     }
7586
7587     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7588     return Standard_True;
7589   }
7590
7591   //! Parse the quaternion.
7592   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7593   {
7594     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7595     if (!anXYZW[0].IsRealValue()
7596      || !anXYZW[1].IsRealValue()
7597      || !anXYZW[2].IsRealValue()
7598      || !anXYZW[3].IsRealValue())
7599     {
7600       return Standard_False;
7601     }
7602
7603     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7604     return Standard_True;
7605   }
7606
7607   //! Auxiliary class for flipping image upside-down.
7608   class ImageFlipper
7609   {
7610   public:
7611
7612     //! Empty constructor.
7613     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7614
7615     //! Perform flipping.
7616     Standard_Boolean FlipY (Image_PixMap& theImage)
7617     {
7618       if (theImage.IsEmpty()
7619        || theImage.SizeX() == 0
7620        || theImage.SizeY() == 0)
7621       {
7622         return Standard_False;
7623       }
7624
7625       const Standard_Size aRowSize = theImage.SizeRowBytes();
7626       if (myTmp.Size() < aRowSize
7627       && !myTmp.Allocate (aRowSize))
7628       {
7629         return Standard_False;
7630       }
7631
7632       // for odd height middle row should be left as is
7633       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7634       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7635       {
7636         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7637         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7638         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7639         memcpy (aTop,               aBot,         aRowSize);
7640         memcpy (aBot,               myTmp.Data(), aRowSize);
7641       }
7642       return Standard_True;
7643     }
7644
7645   private:
7646     NCollection_Buffer myTmp;
7647   };
7648
7649 }
7650
7651 //=================================================================================================
7652 //function : VViewParams
7653 //purpose  : Gets or sets AIS View characteristics
7654 //=================================================================================================
7655 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7656 {
7657   Handle(V3d_View) aView = ViewerTest::CurrentView();
7658   if (aView.IsNull())
7659   {
7660     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7661     return 1;
7662   }
7663
7664   Standard_Boolean toSetProj     = Standard_False;
7665   Standard_Boolean toSetUp       = Standard_False;
7666   Standard_Boolean toSetAt       = Standard_False;
7667   Standard_Boolean toSetEye      = Standard_False;
7668   Standard_Boolean toSetScale    = Standard_False;
7669   Standard_Boolean toSetSize     = Standard_False;
7670   Standard_Boolean toSetCenter2d = Standard_False;
7671   Standard_Real    aViewScale = aView->Scale();
7672   Standard_Real    aViewSize  = 1.0;
7673   Graphic3d_Vec2i  aCenter2d;
7674   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7675   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7676   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7677   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7678   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7679   if (theArgsNb == 1)
7680   {
7681     // print all of the available view parameters
7682     char aText[4096];
7683     Sprintf (aText,
7684              "Scale: %g\n"
7685              "Proj:  %12g %12g %12g\n"
7686              "Up:    %12g %12g %12g\n"
7687              "At:    %12g %12g %12g\n"
7688              "Eye:   %12g %12g %12g\n",
7689               aViewScale,
7690               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7691               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7692               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7693               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7694     theDi << aText;
7695     return 0;
7696   }
7697
7698   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7699   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7700   {
7701     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7702     anArg.LowerCase();
7703     if (anUpdateTool.parseRedrawMode (anArg))
7704     {
7705       continue;
7706     }
7707     else if (anArg == "-cmd"
7708           || anArg == "-command"
7709           || anArg == "-args")
7710     {
7711       char aText[4096];
7712       Sprintf (aText,
7713                "-scale %g "
7714                "-proj %g %g %g "
7715                "-up %g %g %g "
7716                "-at %g %g %g\n",
7717                 aViewScale,
7718                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7719                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7720                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7721       theDi << aText;
7722     }
7723     else if (anArg == "-scale"
7724           || anArg == "-size")
7725     {
7726       if (anArgIter + 1 < theArgsNb
7727        && *theArgVec[anArgIter + 1] != '-')
7728       {
7729         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7730         if (aValueArg.IsRealValue())
7731         {
7732           ++anArgIter;
7733           if (anArg == "-scale")
7734           {
7735             toSetScale = Standard_True;
7736             aViewScale = aValueArg.RealValue();
7737           }
7738           else if (anArg == "-size")
7739           {
7740             toSetSize = Standard_True;
7741             aViewSize = aValueArg.RealValue();
7742           }
7743           continue;
7744         }
7745       }
7746       if (anArg == "-scale")
7747       {
7748         theDi << "Scale: " << aView->Scale() << "\n";
7749       }
7750       else if (anArg == "-size")
7751       {
7752         Graphic3d_Vec2d aSizeXY;
7753         aView->Size (aSizeXY.x(), aSizeXY.y());
7754         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7755       }
7756     }
7757     else if (anArg == "-eye"
7758           || anArg == "-at"
7759           || anArg == "-up"
7760           || anArg == "-proj")
7761     {
7762       if (anArgIter + 3 < theArgsNb)
7763       {
7764         gp_XYZ anXYZ;
7765         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7766         {
7767           anArgIter += 3;
7768           if (anArg == "-eye")
7769           {
7770             toSetEye = Standard_True;
7771             aViewEye = anXYZ;
7772           }
7773           else if (anArg == "-at")
7774           {
7775             toSetAt = Standard_True;
7776             aViewAt = anXYZ;
7777           }
7778           else if (anArg == "-up")
7779           {
7780             toSetUp = Standard_True;
7781             aViewUp = anXYZ;
7782           }
7783           else if (anArg == "-proj")
7784           {
7785             toSetProj = Standard_True;
7786             aViewProj = anXYZ;
7787           }
7788           continue;
7789         }
7790       }
7791
7792       if (anArg == "-eye")
7793       {
7794         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7795       }
7796       else if (anArg == "-at")
7797       {
7798         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7799       }
7800       else if (anArg == "-up")
7801       {
7802         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7803       }
7804       else if (anArg == "-proj")
7805       {
7806         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7807       }
7808     }
7809     else if (anArg == "-center")
7810     {
7811       if (anArgIter + 2 < theArgsNb)
7812       {
7813         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7814         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7815         if (anX.IsIntegerValue()
7816          && anY.IsIntegerValue())
7817         {
7818           toSetCenter2d = Standard_True;
7819           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7820         }
7821       }
7822     }
7823     else
7824     {
7825       std::cout << "Syntax error at '" << anArg << "'\n";
7826       return 1;
7827     }
7828   }
7829
7830   // change view parameters in proper order
7831   if (toSetScale)
7832   {
7833     aView->SetScale (aViewScale);
7834   }
7835   if (toSetSize)
7836   {
7837     aView->SetSize (aViewSize);
7838   }
7839   if (toSetEye)
7840   {
7841     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7842   }
7843   if (toSetAt)
7844   {
7845     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7846   }
7847   if (toSetProj)
7848   {
7849     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7850   }
7851   if (toSetUp)
7852   {
7853     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7854   }
7855   if (toSetCenter2d)
7856   {
7857     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7858   }
7859
7860   return 0;
7861 }
7862
7863 //==============================================================================
7864 //function : V2DMode
7865 //purpose  :
7866 //==============================================================================
7867 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7868 {
7869   bool is2dMode = true;
7870   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7871   if (aV3dView.IsNull())
7872   {
7873     std::cout << "Error: no active view.\n";
7874     return 1;
7875   }
7876   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7877   {
7878     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7879     TCollection_AsciiString anArgCase = anArg;
7880     anArgCase.LowerCase();
7881     if (anArgIt + 1 < theArgsNb
7882      && anArgCase == "-name")
7883     {
7884       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7885       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7886       if (!ViewerTest_myViews.IsBound1 (aViewName))
7887       {
7888         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7889         return 1;
7890       }
7891       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7892     }
7893     else if (anArgCase == "-mode")
7894     {
7895       if (anArgIt + 1 < theArgsNb
7896        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7897       {
7898         ++anArgIt;
7899       }
7900     }
7901     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7902     {
7903       //
7904     }
7905     else
7906     {
7907       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7908       return 1;
7909     }
7910   }
7911
7912   aV3dView->SetView2DMode (is2dMode);
7913   return 0;
7914 }
7915
7916 //==============================================================================
7917 //function : VAnimation
7918 //purpose  :
7919 //==============================================================================
7920 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7921                                     Standard_Integer  theArgNb,
7922                                     const char**      theArgVec)
7923 {
7924   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7925   if (theArgNb < 2)
7926   {
7927     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7928          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7929     {
7930       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7931     }
7932     return 0;
7933   }
7934   if (aCtx.IsNull())
7935   {
7936     std::cout << "Error: no active view\n";
7937     return 1;
7938   }
7939
7940   Standard_Integer anArgIter = 1;
7941   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7942   if (aNameArg.IsEmpty())
7943   {
7944     std::cout << "Syntax error: animation name is not defined.\n";
7945     return 1;
7946   }
7947
7948   TCollection_AsciiString aNameArgLower = aNameArg;
7949   aNameArgLower.LowerCase();
7950   if (aNameArgLower == "-reset"
7951    || aNameArgLower == "-clear")
7952   {
7953     ViewerTest_AnimationTimelineMap.Clear();
7954     return 0;
7955   }
7956   else if (aNameArg.Value (1) == '-')
7957   {
7958     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7959     return 1;
7960   }
7961
7962   const char* aNameSplitter = "/";
7963   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7964   if (aSplitPos == -1)
7965   {
7966     aNameSplitter = ".";
7967     aSplitPos = aNameArg.Search (aNameSplitter);
7968   }
7969
7970   // find existing or create a new animation by specified name within syntax "parent.child".
7971   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
7972   for (; !aNameArg.IsEmpty();)
7973   {
7974     TCollection_AsciiString aNameParent;
7975     if (aSplitPos != -1)
7976     {
7977       if (aSplitPos == aNameArg.Length())
7978       {
7979         std::cout << "Syntax error: animation name is not defined.\n";
7980         return 1;
7981       }
7982
7983       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
7984       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
7985
7986       aSplitPos = aNameArg.Search (aNameSplitter);
7987     }
7988     else
7989     {
7990       aNameParent = aNameArg;
7991       aNameArg.Clear();
7992     }
7993
7994     if (anAnimation.IsNull())
7995     {
7996       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
7997       {
7998         anAnimation = new AIS_Animation (aNameParent);
7999         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8000       }
8001       aRootAnimation = anAnimation;
8002     }
8003     else
8004     {
8005       aParentAnimation = anAnimation;
8006       anAnimation = aParentAnimation->Find (aNameParent);
8007       if (anAnimation.IsNull())
8008       {
8009         anAnimation = new AIS_Animation (aNameParent);
8010         aParentAnimation->Add (anAnimation);
8011       }
8012     }
8013   }
8014
8015   if (anArgIter >= theArgNb)
8016   {
8017     // just print the list of children
8018     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8019     {
8020       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8021     }
8022     return 0;
8023   }
8024
8025   // animation parameters
8026   Standard_Boolean toPlay = Standard_False;
8027   Standard_Real aPlaySpeed     = 1.0;
8028   Standard_Real aPlayStartTime = anAnimation->StartPts();
8029   Standard_Real aPlayDuration  = anAnimation->Duration();
8030   Standard_Boolean isFreeCamera = Standard_False;
8031   Standard_Boolean isLockLoop   = Standard_False;
8032
8033   // video recording parameters
8034   TCollection_AsciiString aRecFile;
8035   Image_VideoParams aRecParams;
8036
8037   Handle(V3d_View) aView = ViewerTest::CurrentView();
8038   for (; anArgIter < theArgNb; ++anArgIter)
8039   {
8040     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8041     anArg.LowerCase();
8042     // general options
8043     if (anArg == "-reset"
8044      || anArg == "-clear")
8045     {
8046       anAnimation->Clear();
8047     }
8048     else if (anArg == "-remove"
8049           || anArg == "-del"
8050           || anArg == "-delete")
8051     {
8052       if (!aParentAnimation.IsNull())
8053       {
8054         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8055       }
8056       else
8057       {
8058         aParentAnimation->Remove (anAnimation);
8059       }
8060     }
8061     // playback options
8062     else if (anArg == "-play")
8063     {
8064       toPlay = Standard_True;
8065       if (++anArgIter < theArgNb)
8066       {
8067         if (*theArgVec[anArgIter] == '-')
8068         {
8069           --anArgIter;
8070           continue;
8071         }
8072         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8073
8074         if (++anArgIter < theArgNb)
8075         {
8076           if (*theArgVec[anArgIter] == '-')
8077           {
8078             --anArgIter;
8079             continue;
8080           }
8081           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8082         }
8083       }
8084     }
8085     else if (anArg == "-resume")
8086     {
8087       toPlay = Standard_True;
8088       aPlayStartTime = anAnimation->ElapsedTime();
8089       if (++anArgIter < theArgNb)
8090       {
8091         if (*theArgVec[anArgIter] == '-')
8092         {
8093           --anArgIter;
8094           continue;
8095         }
8096
8097         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8098       }
8099     }
8100     else if (anArg == "-playspeed"
8101           || anArg == "-speed")
8102     {
8103       if (++anArgIter >= theArgNb)
8104       {
8105         std::cout << "Syntax error at " << anArg << ".\n";
8106         return 1;
8107       }
8108       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8109     }
8110     else if (anArg == "-lock"
8111           || anArg == "-lockloop"
8112           || anArg == "-playlockloop")
8113     {
8114       isLockLoop = Standard_True;
8115     }
8116     else if (anArg == "-freecamera"
8117           || anArg == "-playfreecamera"
8118           || anArg == "-freelook")
8119     {
8120       isFreeCamera = Standard_True;
8121     }
8122     // video recodring options
8123     else if (anArg == "-rec"
8124           || anArg == "-record")
8125     {
8126       if (++anArgIter >= theArgNb)
8127       {
8128         std::cout << "Syntax error at " << anArg << ".\n";
8129         return 1;
8130       }
8131
8132       aRecFile = theArgVec[anArgIter];
8133       if (aRecParams.FpsNum <= 0)
8134       {
8135         aRecParams.FpsNum = 24;
8136       }
8137
8138       if (anArgIter + 2 < theArgNb
8139       && *theArgVec[anArgIter + 1] != '-'
8140       && *theArgVec[anArgIter + 2] != '-')
8141       {
8142         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8143         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8144         if (aWidthArg .IsIntegerValue()
8145          && aHeightArg.IsIntegerValue())
8146         {
8147           aRecParams.Width  = aWidthArg .IntegerValue();
8148           aRecParams.Height = aHeightArg.IntegerValue();
8149           anArgIter += 2;
8150         }
8151       }
8152     }
8153     else if (anArg == "-fps")
8154     {
8155       if (++anArgIter >= theArgNb)
8156       {
8157         std::cout << "Syntax error at " << anArg << ".\n";
8158         return 1;
8159       }
8160
8161       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8162       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8163       if (aSplitIndex == 0)
8164       {
8165         aRecParams.FpsNum = aFpsArg.IntegerValue();
8166       }
8167       else
8168       {
8169         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8170         aFpsArg.Split (aFpsArg.Length() - 1);
8171         const TCollection_AsciiString aNumStr = aFpsArg;
8172         aRecParams.FpsNum = aNumStr.IntegerValue();
8173         aRecParams.FpsDen = aDenStr.IntegerValue();
8174         if (aRecParams.FpsDen < 1)
8175         {
8176           std::cout << "Syntax error at " << anArg << ".\n";
8177           return 1;
8178         }
8179       }
8180     }
8181     else if (anArg == "-format")
8182     {
8183       if (++anArgIter >= theArgNb)
8184       {
8185         std::cout << "Syntax error at " << anArg << ".\n";
8186         return 1;
8187       }
8188       aRecParams.Format = theArgVec[anArgIter];
8189     }
8190     else if (anArg == "-pix_fmt"
8191           || anArg == "-pixfmt"
8192           || anArg == "-pixelformat")
8193     {
8194       if (++anArgIter >= theArgNb)
8195       {
8196         std::cout << "Syntax error at " << anArg << ".\n";
8197         return 1;
8198       }
8199       aRecParams.PixelFormat = theArgVec[anArgIter];
8200     }
8201     else if (anArg == "-codec"
8202           || anArg == "-vcodec"
8203           || anArg == "-videocodec")
8204     {
8205       if (++anArgIter >= theArgNb)
8206       {
8207         std::cout << "Syntax error at " << anArg << ".\n";
8208         return 1;
8209       }
8210       aRecParams.VideoCodec = theArgVec[anArgIter];
8211     }
8212     else if (anArg == "-crf"
8213           || anArg == "-preset"
8214           || anArg == "-qp")
8215     {
8216       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8217       if (++anArgIter >= theArgNb)
8218       {
8219         std::cout << "Syntax error at " << anArg << ".\n";
8220         return 1;
8221       }
8222
8223       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8224     }
8225     // animation definition options
8226     else if (anArg == "-start"
8227           || anArg == "-starttime"
8228           || anArg == "-startpts")
8229     {
8230       if (++anArgIter >= theArgNb)
8231       {
8232         std::cout << "Syntax error at " << anArg << ".\n";
8233         return 1;
8234       }
8235
8236       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8237       aRootAnimation->UpdateTotalDuration();
8238     }
8239     else if (anArg == "-end"
8240           || anArg == "-endtime"
8241           || anArg == "-endpts")
8242     {
8243       if (++anArgIter >= theArgNb)
8244       {
8245         std::cout << "Syntax error at " << anArg << ".\n";
8246         return 1;
8247       }
8248
8249       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8250       aRootAnimation->UpdateTotalDuration();
8251     }
8252     else if (anArg == "-dur"
8253           || anArg == "-duration")
8254     {
8255       if (++anArgIter >= theArgNb)
8256       {
8257         std::cout << "Syntax error at " << anArg << ".\n";
8258         return 1;
8259       }
8260
8261       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8262       aRootAnimation->UpdateTotalDuration();
8263     }
8264     else if (anArg == "-command"
8265           || anArg == "-cmd"
8266           || anArg == "-invoke"
8267           || anArg == "-eval"
8268           || anArg == "-proc")
8269     {
8270       if (++anArgIter >= theArgNb)
8271       {
8272         std::cout << "Syntax error at " << anArg << ".\n";
8273         return 1;
8274       }
8275
8276       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8277       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8278     }
8279     else if (anArg == "-objecttrsf"
8280           || anArg == "-objectransformation"
8281           || anArg == "-objtransformation"
8282           || anArg == "-objtrsf"
8283           || anArg == "-object"
8284           || anArg == "-obj")
8285     {
8286       if (++anArgIter >= theArgNb)
8287       {
8288         std::cout << "Syntax error at " << anArg << ".\n";
8289         return 1;
8290       }
8291
8292       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8293       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8294       Handle(AIS_InteractiveObject) anObject;
8295       if (!aMapOfAIS.Find2 (anObjName, anObject))
8296       {
8297         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8298         return 1;
8299       }
8300
8301       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8302       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8303       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8304       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8305       Standard_Boolean isTrsfSet = Standard_False;
8306       Standard_Integer aTrsfArgIter = anArgIter + 1;
8307       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8308       {
8309         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8310         aTrsfArg.LowerCase();
8311         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8312         if (aTrsfArg.StartsWith ("-rotation")
8313          || aTrsfArg.StartsWith ("-rot"))
8314         {
8315           isTrsfSet = Standard_True;
8316           if (aTrsfArgIter + 4 >= theArgNb
8317           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8318           {
8319             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8320             return 1;
8321           }
8322           aTrsfArgIter += 4;
8323         }
8324         else if (aTrsfArg.StartsWith ("-location")
8325               || aTrsfArg.StartsWith ("-loc"))
8326         {
8327           isTrsfSet = Standard_True;
8328           if (aTrsfArgIter + 3 >= theArgNb
8329           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8330           {
8331             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8332             return 1;
8333           }
8334           aTrsfArgIter += 3;
8335         }
8336         else if (aTrsfArg.StartsWith ("-scale"))
8337         {
8338           isTrsfSet = Standard_True;
8339           if (++aTrsfArgIter >= theArgNb)
8340           {
8341             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8342             return 1;
8343           }
8344
8345           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8346           if (!aScaleStr.IsRealValue())
8347           {
8348             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8349             return 1;
8350           }
8351           aScales[anIndex] = aScaleStr.RealValue();
8352         }
8353         else
8354         {
8355           anArgIter = aTrsfArgIter - 1;
8356           break;
8357         }
8358       }
8359       if (!isTrsfSet)
8360       {
8361         std::cout << "Syntax error at " << anArg << ".\n";
8362         return 1;
8363       }
8364       else if (aTrsfArgIter >= theArgNb)
8365       {
8366         anArgIter = theArgNb;
8367       }
8368
8369       aTrsfs[0].SetRotation        (aRotQuats[0]);
8370       aTrsfs[1].SetRotation        (aRotQuats[1]);
8371       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8372       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8373       aTrsfs[0].SetScaleFactor     (aScales[0]);
8374       aTrsfs[1].SetScaleFactor     (aScales[1]);
8375
8376       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8377       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8378     }
8379     else if (anArg == "-viewtrsf"
8380           || anArg == "-view")
8381     {
8382       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8383       if (aCamAnimation.IsNull())
8384       {
8385         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8386         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8387       }
8388
8389       Handle(Graphic3d_Camera) aCams[2] =
8390       {
8391         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8392         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8393       };
8394
8395       Standard_Boolean isTrsfSet = Standard_False;
8396       Standard_Integer aViewArgIter = anArgIter + 1;
8397       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8398       {
8399         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8400         aViewArg.LowerCase();
8401         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8402         if (aViewArg.StartsWith ("-scale"))
8403         {
8404           isTrsfSet = Standard_True;
8405           if (++aViewArgIter >= theArgNb)
8406           {
8407             std::cout << "Syntax error at " << anArg << ".\n";
8408             return 1;
8409           }
8410
8411           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8412           if (!aScaleStr.IsRealValue())
8413           {
8414             std::cout << "Syntax error at " << aViewArg << ".\n";
8415             return 1;
8416           }
8417           Standard_Real aScale = aScaleStr.RealValue();
8418           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8419           aCams[anIndex]->SetScale (aScale);
8420         }
8421         else if (aViewArg.StartsWith ("-eye")
8422               || aViewArg.StartsWith ("-center")
8423               || aViewArg.StartsWith ("-at")
8424               || aViewArg.StartsWith ("-up"))
8425         {
8426           isTrsfSet = Standard_True;
8427           gp_XYZ anXYZ;
8428           if (aViewArgIter + 3 >= theArgNb
8429           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8430           {
8431             std::cout << "Syntax error at " << aViewArg << ".\n";
8432             return 1;
8433           }
8434           aViewArgIter += 3;
8435
8436           if (aViewArg.StartsWith ("-eye"))
8437           {
8438             aCams[anIndex]->SetEye (anXYZ);
8439           }
8440           else if (aViewArg.StartsWith ("-center")
8441                 || aViewArg.StartsWith ("-at"))
8442           {
8443             aCams[anIndex]->SetCenter (anXYZ);
8444           }
8445           else if (aViewArg.StartsWith ("-up"))
8446           {
8447             aCams[anIndex]->SetUp (anXYZ);
8448           }
8449         }
8450         else
8451         {
8452           anArgIter = aViewArgIter - 1;
8453           break;
8454         }
8455       }
8456       if (!isTrsfSet)
8457       {
8458         std::cout << "Syntax error at " << anArg << ".\n";
8459         return 1;
8460       }
8461       else if (aViewArgIter >= theArgNb)
8462       {
8463         anArgIter = theArgNb;
8464       }
8465
8466       aCamAnimation->SetCameraStart(aCams[0]);
8467       aCamAnimation->SetCameraEnd  (aCams[1]);
8468     }
8469     else
8470     {
8471       std::cout << "Syntax error at " << anArg << ".\n";
8472       return 1;
8473     }
8474   }
8475
8476   if (!toPlay && aRecFile.IsEmpty())
8477   {
8478     return 0;
8479   }
8480
8481   // Start animation timeline and process frame updating.
8482   TheIsAnimating = Standard_True;
8483   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8484   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8485   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8486   if (isFreeCamera)
8487   {
8488     aView->Camera()->Copy (aCameraBack);
8489   }
8490
8491   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8492   if (aRecParams.FpsNum <= 0)
8493   {
8494     while (!anAnimation->IsStopped())
8495     {
8496       aCameraBack->Copy (aView->Camera());
8497       const Standard_Real aPts = anAnimation->UpdateTimer();
8498       if (isFreeCamera)
8499       {
8500         aView->Camera()->Copy (aCameraBack);
8501       }
8502
8503       if (aPts >= anUpperPts)
8504       {
8505         anAnimation->Pause();
8506         break;
8507       }
8508
8509       if (aView->IsInvalidated())
8510       {
8511         aView->Redraw();
8512       }
8513       else
8514       {
8515         aView->RedrawImmediate();
8516       }
8517
8518       if (!isLockLoop)
8519       {
8520         // handle user events
8521         theDI.Eval ("after 1 set waiter 1");
8522         theDI.Eval ("vwait waiter");
8523       }
8524       if (!TheIsAnimating)
8525       {
8526         anAnimation->Pause();
8527         theDI << aPts;
8528         break;
8529       }
8530     }
8531
8532     if (aView->IsInvalidated())
8533     {
8534       aView->Redraw();
8535     }
8536     else
8537     {
8538       aView->RedrawImmediate();
8539     }
8540   }
8541   else
8542   {
8543     OSD_Timer aPerfTimer;
8544     aPerfTimer.Start();
8545
8546     Handle(Image_VideoRecorder) aRecorder;
8547     ImageFlipper aFlipper;
8548     Handle(Draw_ProgressIndicator) aProgress;
8549     if (!aRecFile.IsEmpty())
8550     {
8551       if (aRecParams.Width  <= 0
8552        || aRecParams.Height <= 0)
8553       {
8554         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8555       }
8556
8557       aRecorder = new Image_VideoRecorder();
8558       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8559       {
8560         std::cout << "Error: failed to open video file for recording\n";
8561         return 0;
8562       }
8563
8564       aProgress = new Draw_ProgressIndicator (theDI, 1);
8565     }
8566
8567     // Manage frame-rated animation here
8568     Standard_Real aPts = aPlayStartTime;
8569     int64_t aNbFrames = 0;
8570     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8571     Standard_Integer aSecondsProgress = 0;
8572     for (; aPts <= anUpperPts && aPSentry.More();)
8573     {
8574       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8575       aPts = aPlayStartTime + aRecPts;
8576       ++aNbFrames;
8577       if (!anAnimation->Update (aPts))
8578       {
8579         break;
8580       }
8581
8582       if (!aRecorder.IsNull())
8583       {
8584         V3d_ImageDumpOptions aDumpParams;
8585         aDumpParams.Width          = aRecParams.Width;
8586         aDumpParams.Height         = aRecParams.Height;
8587         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8588         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8589         aDumpParams.ToAdjustAspect = Standard_True;
8590         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8591         {
8592           std::cout << "Error: view dump is failed!\n";
8593           return 0;
8594         }
8595         aFlipper.FlipY (aRecorder->ChangeFrame());
8596         if (!aRecorder->PushFrame())
8597         {
8598           return 0;
8599         }
8600       }
8601       else
8602       {
8603         aView->Redraw();
8604       }
8605
8606       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8607       {
8608         aPSentry.Next();
8609         ++aSecondsProgress;
8610       }
8611     }
8612
8613     aPerfTimer.Stop();
8614     anAnimation->Stop();
8615     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8616     theDI << "Average FPS: " << aRecFps << "\n"
8617           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8618
8619     aView->Redraw();
8620   }
8621
8622   aView->SetImmediateUpdate (wasImmediateUpdate);
8623   TheIsAnimating = Standard_False;
8624   return 0;
8625 }
8626
8627
8628 //=======================================================================
8629 //function : VChangeSelected
8630 //purpose  : Adds the shape to selection or remove one from it
8631 //=======================================================================
8632 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8633                                 Standard_Integer argc,
8634                                 const char ** argv)
8635 {
8636   if(argc != 2)
8637   {
8638     di<<"Usage : " << argv[0] << " shape \n";
8639     return 1;
8640   }
8641   //get AIS_Shape:
8642   TCollection_AsciiString aName(argv[1]);
8643   Handle(AIS_InteractiveObject) anAISObject;
8644   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8645     || anAISObject.IsNull())
8646   {
8647     di<<"Use 'vdisplay' before";
8648     return 1;
8649   }
8650
8651   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8652   return 0;
8653 }
8654
8655 //=======================================================================
8656 //function : VNbSelected
8657 //purpose  : Returns number of selected objects
8658 //=======================================================================
8659 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8660                                 Standard_Integer argc,
8661                                 const char ** argv)
8662 {
8663   if(argc != 1)
8664   {
8665     di << "Usage : " << argv[0] << "\n";
8666     return 1;
8667   }
8668   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8669   if(aContext.IsNull())
8670   {
8671     di << "use 'vinit' command before " << argv[0] << "\n";
8672     return 1;
8673   }
8674   di << aContext->NbSelected() << "\n";
8675   return 0;
8676 }
8677
8678 //=======================================================================
8679 //function : VPurgeDisplay
8680 //purpose  : Switches altialiasing on or off
8681 //=======================================================================
8682 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8683                                 Standard_Integer argc,
8684                                 const char ** argv)
8685 {
8686   if (argc > 1)
8687   {
8688     di << "Usage : " << argv[0] << "\n";
8689     return 1;
8690   }
8691   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8692   if (aContext.IsNull())
8693   {
8694     di << "use 'vinit' command before " << argv[0] << "\n";
8695     return 1;
8696   }
8697
8698   di << aContext->PurgeDisplay() << "\n";
8699   return 0;
8700 }
8701
8702 //=======================================================================
8703 //function : VSetViewSize
8704 //purpose  :
8705 //=======================================================================
8706 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8707                                 Standard_Integer argc,
8708                                 const char ** argv)
8709 {
8710   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8711   if(aContext.IsNull())
8712   {
8713     di << "use 'vinit' command before " << argv[0] << "\n";
8714     return 1;
8715   }
8716   if(argc != 2)
8717   {
8718     di<<"Usage : " << argv[0] << " Size\n";
8719     return 1;
8720   }
8721   Standard_Real aSize = Draw::Atof (argv[1]);
8722   if (aSize <= 0.)
8723   {
8724     di<<"Bad Size value  : " << aSize << "\n";
8725     return 1;
8726   }
8727
8728   Handle(V3d_View) aView = ViewerTest::CurrentView();
8729   aView->SetSize(aSize);
8730   return 0;
8731 }
8732
8733 //=======================================================================
8734 //function : VMoveView
8735 //purpose  :
8736 //=======================================================================
8737 static Standard_Integer VMoveView (Draw_Interpretor& di,
8738                                 Standard_Integer argc,
8739                                 const char ** argv)
8740 {
8741   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8742   if(aContext.IsNull())
8743   {
8744     di << "use 'vinit' command before " << argv[0] << "\n";
8745     return 1;
8746   }
8747   if(argc < 4 || argc > 5)
8748   {
8749     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8750     return 1;
8751   }
8752   Standard_Real Dx = Draw::Atof (argv[1]);
8753   Standard_Real Dy = Draw::Atof (argv[2]);
8754   Standard_Real Dz = Draw::Atof (argv[3]);
8755   Standard_Boolean aStart = Standard_True;
8756   if (argc == 5)
8757   {
8758       aStart = (Draw::Atoi (argv[4]) > 0);
8759   }
8760
8761   Handle(V3d_View) aView = ViewerTest::CurrentView();
8762   aView->Move(Dx,Dy,Dz,aStart);
8763   return 0;
8764 }
8765
8766 //=======================================================================
8767 //function : VTranslateView
8768 //purpose  :
8769 //=======================================================================
8770 static Standard_Integer VTranslateView (Draw_Interpretor& di,
8771                                 Standard_Integer argc,
8772                                 const char ** argv)
8773 {
8774   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8775   if(aContext.IsNull())
8776   {
8777     di << "use 'vinit' command before " << argv[0] << "\n";
8778     return 1;
8779   }
8780   if(argc < 4 || argc > 5)
8781   {
8782     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8783     return 1;
8784   }
8785   Standard_Real Dx = Draw::Atof (argv[1]);
8786   Standard_Real Dy = Draw::Atof (argv[2]);
8787   Standard_Real Dz = Draw::Atof (argv[3]);
8788   Standard_Boolean aStart = Standard_True;
8789   if (argc == 5)
8790   {
8791       aStart = (Draw::Atoi (argv[4]) > 0);
8792   }
8793
8794   Handle(V3d_View) aView = ViewerTest::CurrentView();
8795   aView->Translate(Dx,Dy,Dz,aStart);
8796   return 0;
8797 }
8798
8799 //=======================================================================
8800 //function : VTurnView
8801 //purpose  :
8802 //=======================================================================
8803 static Standard_Integer VTurnView (Draw_Interpretor& di,
8804                                 Standard_Integer argc,
8805                                 const char ** argv)
8806 {
8807   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8808   if(aContext.IsNull()) {
8809     di << "use 'vinit' command before " << argv[0] << "\n";
8810     return 1;
8811   }
8812   if(argc < 4 || argc > 5){
8813     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8814     return 1;
8815   }
8816   Standard_Real Ax = Draw::Atof (argv[1]);
8817   Standard_Real Ay = Draw::Atof (argv[2]);
8818   Standard_Real Az = Draw::Atof (argv[3]);
8819   Standard_Boolean aStart = Standard_True;
8820   if (argc == 5)
8821   {
8822       aStart = (Draw::Atoi (argv[4]) > 0);
8823   }
8824
8825   Handle(V3d_View) aView = ViewerTest::CurrentView();
8826   aView->Turn(Ax,Ay,Az,aStart);
8827   return 0;
8828 }
8829
8830 //==============================================================================
8831 //function : VTextureEnv
8832 //purpose  : ENables or disables environment mapping
8833 //==============================================================================
8834 class OCC_TextureEnv : public Graphic3d_TextureEnv
8835 {
8836 public:
8837   OCC_TextureEnv(const Standard_CString FileName);
8838   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8839   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8840                             const Standard_Boolean theModulateFlag,
8841                             const Graphic3d_TypeOfTextureFilter theFilter,
8842                             const Standard_ShortReal theXScale,
8843                             const Standard_ShortReal theYScale,
8844                             const Standard_ShortReal theXShift,
8845                             const Standard_ShortReal theYShift,
8846                             const Standard_ShortReal theAngle);
8847   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8848 };
8849 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8850
8851 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8852   : Graphic3d_TextureEnv(theFileName)
8853 {
8854 }
8855
8856 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8857   : Graphic3d_TextureEnv(theTexId)
8858 {
8859 }
8860
8861 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8862                                           const Standard_Boolean theModulateFlag,
8863                                           const Graphic3d_TypeOfTextureFilter theFilter,
8864                                           const Standard_ShortReal theXScale,
8865                                           const Standard_ShortReal theYScale,
8866                                           const Standard_ShortReal theXShift,
8867                                           const Standard_ShortReal theYShift,
8868                                           const Standard_ShortReal theAngle)
8869 {
8870   myParams->SetRepeat     (theRepeatFlag);
8871   myParams->SetModulate   (theModulateFlag);
8872   myParams->SetFilter     (theFilter);
8873   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8874   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8875   myParams->SetRotation   (theAngle);
8876 }
8877
8878 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8879 {
8880   // get the active view
8881   Handle(V3d_View) aView = ViewerTest::CurrentView();
8882   if (aView.IsNull())
8883   {
8884     std::cerr << "No active view. Please call vinit.\n";
8885     return 1;
8886   }
8887
8888   // Checking the input arguments
8889   Standard_Boolean anEnableFlag = Standard_False;
8890   Standard_Boolean isOk         = theArgNb >= 2;
8891   if (isOk)
8892   {
8893     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8894     anEnableFlag = anEnableOpt.IsEqual("on");
8895     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8896   }
8897   if (anEnableFlag)
8898   {
8899     isOk = (theArgNb == 3 || theArgNb == 11);
8900     if (isOk)
8901     {
8902       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8903       isOk = (!aTextureOpt.IsIntegerValue() ||
8904              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8905
8906       if (isOk && theArgNb == 11)
8907       {
8908         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8909                                 aModulateOpt(theArgVec[4]),
8910                                 aFilterOpt  (theArgVec[5]),
8911                                 aSScaleOpt  (theArgVec[6]),
8912                                 aTScaleOpt  (theArgVec[7]),
8913                                 aSTransOpt  (theArgVec[8]),
8914                                 aTTransOpt  (theArgVec[9]),
8915                                 anAngleOpt  (theArgVec[10]);
8916         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8917                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8918                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8919                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8920                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8921                 anAngleOpt.IsRealValue());
8922       }
8923     }
8924   }
8925
8926   if (!isOk)
8927   {
8928     std::cerr << "Usage :" << std::endl;
8929     std::cerr << theArgVec[0] << " off" << std::endl;
8930     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;
8931     return 1;
8932   }
8933
8934   if (anEnableFlag)
8935   {
8936     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8937     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8938                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8939                                      new OCC_TextureEnv(theArgVec[2]);
8940
8941     if (theArgNb == 11)
8942     {
8943       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8944       aTexEnv->SetTextureParameters(
8945         aRepeatOpt.  IsEqual("repeat"),
8946         aModulateOpt.IsEqual("modulate"),
8947         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8948                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8949                                                                            Graphic3d_TOTF_TRILINEAR,
8950         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8951         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8952         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8953         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8954         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8955         );
8956     }
8957     aView->SetTextureEnv(aTexEnv);
8958   }
8959   else // Disabling environment mapping
8960   {
8961     Handle(Graphic3d_TextureEnv) aTexture;
8962     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8963   }
8964
8965   aView->Redraw();
8966   return 0;
8967 }
8968
8969 namespace
8970 {
8971   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
8972
8973   //! Remove registered clipping plane from all views and objects.
8974   static void removePlane (MapOfPlanes& theRegPlanes,
8975                            const TCollection_AsciiString& theName)
8976   {
8977     Handle(Graphic3d_ClipPlane) aClipPlane;
8978     if (!theRegPlanes.Find (theName, aClipPlane))
8979     {
8980       std::cout << "Warning: no such plane.\n";
8981       return;
8982     }
8983
8984     theRegPlanes.UnBind (theName);
8985     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
8986          anIObjIt.More(); anIObjIt.Next())
8987     {
8988       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
8989       aPrs->RemoveClipPlane (aClipPlane);
8990     }
8991
8992     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
8993          aViewIt.More(); aViewIt.Next())
8994     {
8995       const Handle(V3d_View)& aView = aViewIt.Key2();
8996       aView->RemoveClipPlane(aClipPlane);
8997     }
8998
8999     ViewerTest::RedrawAllViews();
9000   }
9001 }
9002
9003 //===============================================================================================
9004 //function : VClipPlane
9005 //purpose  :
9006 //===============================================================================================
9007 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9008 {
9009   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9010   static MapOfPlanes aRegPlanes;
9011
9012   if (theArgsNb < 2)
9013   {
9014     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9015     {
9016       theDi << aPlaneIter.Key() << " ";
9017     }
9018     return 0;
9019   }
9020
9021   TCollection_AsciiString aCommand (theArgVec[1]);
9022   aCommand.LowerCase();
9023   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9024   if (anActiveView.IsNull())
9025   {
9026     std::cout << "Error: no active view.\n";
9027     return 1;
9028   }
9029
9030   // print maximum number of planes for current viewer
9031   if (aCommand == "-maxplanes"
9032    || aCommand == "maxplanes")
9033   {
9034     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9035           << " plane slots provided by driver.\n";
9036     return 0;
9037   }
9038
9039   // create / delete plane instance
9040   if (aCommand == "-create"
9041    || aCommand == "create"
9042    || aCommand == "-delete"
9043    || aCommand == "delete"
9044    || aCommand == "-clone"
9045    || aCommand == "clone")
9046   {
9047     if (theArgsNb < 3)
9048     {
9049       std::cout << "Syntax error: plane name is required.\n";
9050       return 1;
9051     }
9052
9053     Standard_Boolean toCreate = aCommand == "-create"
9054                              || aCommand == "create";
9055     Standard_Boolean toClone  = aCommand == "-clone"
9056                              || aCommand == "clone";
9057     Standard_Boolean toDelete = aCommand == "-delete"
9058                              || aCommand == "delete";
9059     TCollection_AsciiString aPlane (theArgVec[2]);
9060
9061     if (toCreate)
9062     {
9063       if (aRegPlanes.IsBound (aPlane))
9064       {
9065         std::cout << "Warning: existing plane has been overridden.\n";
9066         toDelete = true;
9067       }
9068       else
9069       {
9070         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9071         return 0;
9072       }
9073     }
9074     else if (toClone) // toClone
9075     {
9076       if (!aRegPlanes.IsBound (aPlane))
9077       {
9078         std::cout << "Error: no such plane.\n";
9079         return 1;
9080       }
9081       else if (theArgsNb < 4)
9082       {
9083         std::cout << "Syntax error: enter name for new plane.\n";
9084         return 1;
9085       }
9086
9087       TCollection_AsciiString aClone (theArgVec[3]);
9088       if (aRegPlanes.IsBound (aClone))
9089       {
9090         std::cout << "Error: plane name is in use.\n";
9091         return 1;
9092       }
9093
9094       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9095
9096       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9097       return 0;
9098     }
9099
9100     if (toDelete)
9101     {
9102       if (aPlane == "ALL"
9103        || aPlane == "all"
9104        || aPlane == "*")
9105       {
9106         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9107         {
9108           aPlane = aPlaneIter.Key();
9109           removePlane (aRegPlanes, aPlane);
9110           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9111         }
9112       }
9113       else
9114       {
9115         removePlane (aRegPlanes, aPlane);
9116       }
9117     }
9118
9119     if (toCreate)
9120     {
9121       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9122     }
9123     return 0;
9124   }
9125
9126   // set / unset plane command
9127   if (aCommand == "set"
9128    || aCommand == "unset")
9129   {
9130     if (theArgsNb < 5)
9131     {
9132       std::cout << "Syntax error: need more arguments.\n";
9133       return 1;
9134     }
9135
9136     // redirect to new syntax
9137     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9138     anArgVec.SetValue (1, theArgVec[0]);
9139     anArgVec.SetValue (2, theArgVec[2]);
9140     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9141     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9142     {
9143       anArgVec.SetValue (anIt, theArgVec[anIt]);
9144     }
9145
9146     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9147   }
9148
9149   // change plane command
9150   TCollection_AsciiString aPlaneName;
9151   Handle(Graphic3d_ClipPlane) aClipPlane;
9152   Standard_Integer anArgIter = 0;
9153   if (aCommand == "-change"
9154    || aCommand == "change")
9155   {
9156     // old syntax support
9157     if (theArgsNb < 3)
9158     {
9159       std::cout << "Syntax error: need more arguments.\n";
9160       return 1;
9161     }
9162
9163     anArgIter  = 3;
9164     aPlaneName = theArgVec[2];
9165     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9166     {
9167       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9168       return 1;
9169     }
9170   }
9171   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9172   {
9173     anArgIter  = 2;
9174     aPlaneName = theArgVec[1];
9175   }
9176   else
9177   {
9178     anArgIter  = 2;
9179     aPlaneName = theArgVec[1];
9180     aClipPlane = new Graphic3d_ClipPlane();
9181     aRegPlanes.Bind (aPlaneName, aClipPlane);
9182     theDi << "Created new plane " << aPlaneName << ".\n";
9183   }
9184
9185   if (theArgsNb - anArgIter < 1)
9186   {
9187     std::cout << "Syntax error: need more arguments.\n";
9188     return 1;
9189   }
9190
9191   for (; anArgIter < theArgsNb; ++anArgIter)
9192   {
9193     const char**     aChangeArgs   = theArgVec + anArgIter;
9194     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9195     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9196     aChangeArg.LowerCase();
9197
9198     Standard_Boolean toEnable = Standard_True;
9199     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9200     {
9201       aClipPlane->SetOn (toEnable);
9202     }
9203     else if (aChangeArg.StartsWith ("-equation")
9204           || aChangeArg.StartsWith ("equation"))
9205     {
9206       if (aNbChangeArgs < 5)
9207       {
9208         std::cout << "Syntax error: need more arguments.\n";
9209         return 1;
9210       }
9211
9212       Standard_Integer aSubIndex = 1;
9213       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9214       if (aPrefixLen < aChangeArg.Length())
9215       {
9216         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9217         if (!aSubStr.IsIntegerValue()
9218           || aSubStr.IntegerValue() <= 0)
9219         {
9220           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9221           return 1;
9222         }
9223         aSubIndex = aSubStr.IntegerValue();
9224       }
9225
9226       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9227       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9228       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9229       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9230       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9231       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9232       {
9233         if (aSubPln->ChainNextPlane().IsNull())
9234         {
9235           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9236         }
9237         aSubPln = aSubPln->ChainNextPlane();
9238       }
9239       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9240       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9241       anArgIter += 4;
9242     }
9243     else if ((aChangeArg == "-boxinterior"
9244            || aChangeArg == "-boxint"
9245            || aChangeArg == "-box")
9246             && aNbChangeArgs >= 7)
9247     {
9248       Graphic3d_BndBox3d aBndBox;
9249       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9250       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9251       anArgIter += 6;
9252
9253       Standard_Integer aNbSubPlanes = 6;
9254       const Graphic3d_Vec3d aDirArray[6] =
9255       {
9256         Graphic3d_Vec3d (-1, 0, 0),
9257         Graphic3d_Vec3d ( 1, 0, 0),
9258         Graphic3d_Vec3d ( 0,-1, 0),
9259         Graphic3d_Vec3d ( 0, 1, 0),
9260         Graphic3d_Vec3d ( 0, 0,-1),
9261         Graphic3d_Vec3d ( 0, 0, 1),
9262       };
9263       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9264       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9265       {
9266         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9267         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9268         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9269         if (aSubPlaneIter + 1 == aNbSubPlanes)
9270         {
9271           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9272         }
9273         else
9274         {
9275           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9276         }
9277         aSubPln = aSubPln->ChainNextPlane();
9278       }
9279     }
9280     else if (aChangeArg == "-capping"
9281           || aChangeArg == "capping")
9282     {
9283       if (aNbChangeArgs < 2)
9284       {
9285         std::cout << "Syntax error: need more arguments.\n";
9286         return 1;
9287       }
9288
9289       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9290       {
9291         aClipPlane->SetCapping (toEnable);
9292         anArgIter += 1;
9293       }
9294       else
9295       {
9296         // just skip otherwise (old syntax)
9297       }
9298     }
9299     else if (aChangeArg == "-useobjectmaterial"
9300           || aChangeArg == "-useobjectmat"
9301           || aChangeArg == "-useobjmat"
9302           || aChangeArg == "-useobjmaterial")
9303     {
9304       if (aNbChangeArgs < 2)
9305       {
9306         std::cout << "Syntax error: need more arguments.\n";
9307         return 1;
9308       }
9309
9310       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9311       {
9312         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9313         anArgIter += 1;
9314       }
9315     }
9316     else if (aChangeArg == "-useobjecttexture"
9317           || aChangeArg == "-useobjecttex"
9318           || aChangeArg == "-useobjtexture"
9319           || aChangeArg == "-useobjtex")
9320     {
9321       if (aNbChangeArgs < 2)
9322       {
9323         std::cout << "Syntax error: need more arguments.\n";
9324         return 1;
9325       }
9326
9327       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9328       {
9329         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9330         anArgIter += 1;
9331       }
9332     }
9333     else if (aChangeArg == "-useobjectshader"
9334           || aChangeArg == "-useobjshader")
9335     {
9336       if (aNbChangeArgs < 2)
9337       {
9338         std::cout << "Syntax error: need more arguments.\n";
9339         return 1;
9340       }
9341
9342       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9343       {
9344         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9345         anArgIter += 1;
9346       }
9347     }
9348     else if (aChangeArg == "-color"
9349           || aChangeArg == "color")
9350     {
9351       Quantity_Color aColor;
9352       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9353                                                            aChangeArgs + 1,
9354                                                            aColor);
9355       if (aNbParsed == 0)
9356       {
9357         std::cout << "Syntax error: need more arguments.\n";
9358         return 1;
9359       }
9360
9361       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9362       aMat.SetAmbientColor (aColor);
9363       aMat.SetDiffuseColor (aColor);
9364       aClipPlane->SetCappingMaterial (aMat);
9365       anArgIter += aNbParsed;
9366     }
9367     else if ((aChangeArg == "-transparency"
9368            || aChangeArg == "-transp")
9369           && aNbChangeArgs >= 2)
9370     {
9371       TCollection_AsciiString aValStr (aChangeArgs[1]);
9372       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9373       if (aValStr.IsRealValue())
9374       {
9375         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9376         aMat.SetTransparency ((float )aValStr.RealValue());
9377         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9378         aClipPlane->SetCappingMaterial (aMat);
9379       }
9380       else
9381       {
9382         aValStr.LowerCase();
9383         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9384         if (aValStr == "opaque")
9385         {
9386           aMode = Graphic3d_AlphaMode_Opaque;
9387         }
9388         else if (aValStr == "mask")
9389         {
9390           aMode = Graphic3d_AlphaMode_Mask;
9391         }
9392         else if (aValStr == "blend")
9393         {
9394           aMode = Graphic3d_AlphaMode_Blend;
9395         }
9396         else if (aValStr == "blendauto")
9397         {
9398           aMode = Graphic3d_AlphaMode_BlendAuto;
9399         }
9400         else
9401         {
9402           std::cout << "Syntax error at '" << aValStr << "'\n";
9403           return 1;
9404         }
9405         anAspect->SetAlphaMode (aMode);
9406         aClipPlane->SetCappingAspect (anAspect);
9407       }
9408       anArgIter += 1;
9409     }
9410     else if (aChangeArg == "-texname"
9411           || aChangeArg == "texname")
9412     {
9413       if (aNbChangeArgs < 2)
9414       {
9415         std::cout << "Syntax error: need more arguments.\n";
9416         return 1;
9417       }
9418
9419       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9420       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9421       if (!aTexture->IsDone())
9422       {
9423         aClipPlane->SetCappingTexture (NULL);
9424       }
9425       else
9426       {
9427         aTexture->EnableModulate();
9428         aTexture->EnableRepeat();
9429         aClipPlane->SetCappingTexture (aTexture);
9430       }
9431       anArgIter += 1;
9432     }
9433     else if (aChangeArg == "-texscale"
9434           || aChangeArg == "texscale")
9435     {
9436       if (aClipPlane->CappingTexture().IsNull())
9437       {
9438         std::cout << "Error: no texture is set.\n";
9439         return 1;
9440       }
9441
9442       if (aNbChangeArgs < 3)
9443       {
9444         std::cout << "Syntax error: need more arguments.\n";
9445         return 1;
9446       }
9447
9448       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9449       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9450       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9451       anArgIter += 2;
9452     }
9453     else if (aChangeArg == "-texorigin"
9454           || aChangeArg == "texorigin") // texture origin
9455     {
9456       if (aClipPlane->CappingTexture().IsNull())
9457       {
9458         std::cout << "Error: no texture is set.\n";
9459         return 1;
9460       }
9461
9462       if (aNbChangeArgs < 3)
9463       {
9464         std::cout << "Syntax error: need more arguments.\n";
9465         return 1;
9466       }
9467
9468       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9469       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9470
9471       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9472       anArgIter += 2;
9473     }
9474     else if (aChangeArg == "-texrotate"
9475           || aChangeArg == "texrotate") // texture rotation
9476     {
9477       if (aClipPlane->CappingTexture().IsNull())
9478       {
9479         std::cout << "Error: no texture is set.\n";
9480         return 1;
9481       }
9482
9483       if (aNbChangeArgs < 2)
9484       {
9485         std::cout << "Syntax error: need more arguments.\n";
9486         return 1;
9487       }
9488
9489       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9490       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9491       anArgIter += 1;
9492     }
9493     else if (aChangeArg == "-hatch"
9494           || aChangeArg == "hatch")
9495     {
9496       if (aNbChangeArgs < 2)
9497       {
9498         std::cout << "Syntax error: need more arguments.\n";
9499         return 1;
9500       }
9501
9502       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9503       aHatchStr.LowerCase();
9504       if (aHatchStr == "on")
9505       {
9506         aClipPlane->SetCappingHatchOn();
9507       }
9508       else if (aHatchStr == "off")
9509       {
9510         aClipPlane->SetCappingHatchOff();
9511       }
9512       else
9513       {
9514         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9515       }
9516       anArgIter += 1;
9517     }
9518     else if (aChangeArg == "-delete"
9519           || aChangeArg == "delete")
9520     {
9521       removePlane (aRegPlanes, aPlaneName);
9522       return 0;
9523     }
9524     else if (aChangeArg == "-set"
9525           || aChangeArg == "-unset"
9526           || aChangeArg == "-setoverrideglobal")
9527     {
9528       // set / unset plane command
9529       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9530       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9531       Standard_Integer anIt = 1;
9532       for (; anIt < aNbChangeArgs; ++anIt)
9533       {
9534         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9535         if (anEntityName.IsEmpty()
9536          || anEntityName.Value (1) == '-')
9537         {
9538           break;
9539         }
9540         else if (!toOverrideGlobal
9541                && ViewerTest_myViews.IsBound1 (anEntityName))
9542         {
9543           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9544           if (toSet)
9545           {
9546             aView->AddClipPlane (aClipPlane);
9547           }
9548           else
9549           {
9550             aView->RemoveClipPlane (aClipPlane);
9551           }
9552           continue;
9553         }
9554         else if (GetMapOfAIS().IsBound2 (anEntityName))
9555         {
9556           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9557           if (toSet)
9558           {
9559             aIObj->AddClipPlane (aClipPlane);
9560           }
9561           else
9562           {
9563             aIObj->RemoveClipPlane (aClipPlane);
9564           }
9565           if (!aIObj->ClipPlanes().IsNull())
9566           {
9567             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9568           }
9569         }
9570         else
9571         {
9572           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9573           return 1;
9574         }
9575       }
9576
9577       if (anIt == 1)
9578       {
9579         // apply to active view
9580         if (toSet)
9581         {
9582           anActiveView->AddClipPlane (aClipPlane);
9583         }
9584         else
9585         {
9586           anActiveView->RemoveClipPlane (aClipPlane);
9587         }
9588       }
9589       else
9590       {
9591         anArgIter = anArgIter + anIt - 1;
9592       }
9593     }
9594     else
9595     {
9596       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9597       return 1;
9598     }
9599   }
9600
9601   ViewerTest::RedrawAllViews();
9602   return 0;
9603 }
9604
9605 //===============================================================================================
9606 //function : VZRange
9607 //purpose  :
9608 //===============================================================================================
9609 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9610 {
9611   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9612
9613   if (aCurrentView.IsNull())
9614   {
9615     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9616     return 1;
9617   }
9618
9619   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9620
9621   if (theArgsNb < 2)
9622   {
9623     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9624     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9625     return 0;
9626   }
9627
9628   if (theArgsNb == 3)
9629   {
9630     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9631     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9632
9633     if (aNewZNear >= aNewZFar)
9634     {
9635       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9636       return 1;
9637     }
9638
9639     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9640     {
9641       std::cout << theArgVec[0] << ": invalid arguments: ";
9642       std::cout << "znear, zfar should be positive for perspective camera.\n";
9643       return 1;
9644     }
9645
9646     aCamera->SetZRange (aNewZNear, aNewZFar);
9647   }
9648   else
9649   {
9650     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9651     return 1;
9652   }
9653
9654   aCurrentView->Redraw();
9655
9656   return 0;
9657 }
9658
9659 //===============================================================================================
9660 //function : VAutoZFit
9661 //purpose  :
9662 //===============================================================================================
9663 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9664 {
9665   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9666
9667   if (aCurrentView.IsNull())
9668   {
9669     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9670     return 1;
9671   }
9672
9673   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9674
9675   if (theArgsNb > 3)
9676   {
9677     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9678     return 1;
9679   }
9680
9681   if (theArgsNb < 2)
9682   {
9683     theDi << "Auto z-fit mode: \n"
9684           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9685           << "Scale: " << aScale << "\n";
9686     return 0;
9687   }
9688
9689   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9690
9691   if (theArgsNb >= 3)
9692   {
9693     aScale = Draw::Atoi (theArgVec[2]);
9694   }
9695
9696   aCurrentView->SetAutoZFitMode (isOn, aScale);
9697   aCurrentView->AutoZFit();
9698   aCurrentView->Redraw();
9699
9700   return 0;
9701 }
9702
9703 //! Auxiliary function to print projection type
9704 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9705 {
9706   switch (theProjType)
9707   {
9708     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9709     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9710     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9711     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9712     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9713   }
9714   return "UNKNOWN";
9715 }
9716
9717 //===============================================================================================
9718 //function : VCamera
9719 //purpose  :
9720 //===============================================================================================
9721 static int VCamera (Draw_Interpretor& theDI,
9722                     Standard_Integer  theArgsNb,
9723                     const char**      theArgVec)
9724 {
9725   Handle(V3d_View) aView = ViewerTest::CurrentView();
9726   if (aView.IsNull())
9727   {
9728     std::cout << "Error: no active view.\n";
9729     return 1;
9730   }
9731
9732   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9733   if (theArgsNb < 2)
9734   {
9735     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9736     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9737     theDI << "Distance:   " << aCamera->Distance() << "\n";
9738     theDI << "IOD:        " << aCamera->IOD() << "\n";
9739     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9740     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9741     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9742     return 0;
9743   }
9744
9745   TCollection_AsciiString aPrsName;
9746   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9747   {
9748     Standard_CString        anArg = theArgVec[anArgIter];
9749     TCollection_AsciiString anArgCase (anArg);
9750     anArgCase.LowerCase();
9751     if (anArgCase == "-proj"
9752      || anArgCase == "-projection"
9753      || anArgCase == "-projtype"
9754      || anArgCase == "-projectiontype")
9755     {
9756       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9757     }
9758     else if (anArgCase == "-ortho"
9759           || anArgCase == "-orthographic")
9760     {
9761       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
9762     }
9763     else if (anArgCase == "-persp"
9764           || anArgCase == "-perspective"
9765           || anArgCase == "-perspmono"
9766           || anArgCase == "-perspectivemono"
9767           || anArgCase == "-mono")
9768     {
9769       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9770     }
9771     else if (anArgCase == "-stereo"
9772           || anArgCase == "-stereoscopic"
9773           || anArgCase == "-perspstereo"
9774           || anArgCase == "-perspectivestereo")
9775     {
9776       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9777     }
9778     else if (anArgCase == "-left"
9779           || anArgCase == "-lefteye"
9780           || anArgCase == "-monoleft"
9781           || anArgCase == "-monolefteye"
9782           || anArgCase == "-perpsleft"
9783           || anArgCase == "-perpslefteye")
9784     {
9785       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9786     }
9787     else if (anArgCase == "-right"
9788           || anArgCase == "-righteye"
9789           || anArgCase == "-monoright"
9790           || anArgCase == "-monorighteye"
9791           || anArgCase == "-perpsright")
9792     {
9793       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9794     }
9795     else if (anArgCase == "-dist"
9796           || anArgCase == "-distance")
9797     {
9798       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9799       if (anArgValue != NULL
9800       && *anArgValue != '-')
9801       {
9802         ++anArgIter;
9803         aCamera->SetDistance (Draw::Atof (anArgValue));
9804         continue;
9805       }
9806       theDI << aCamera->Distance() << " ";
9807     }
9808     else if (anArgCase == "-iod")
9809     {
9810       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9811       if (anArgValue != NULL
9812       && *anArgValue != '-')
9813       {
9814         ++anArgIter;
9815         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9816         continue;
9817       }
9818       theDI << aCamera->IOD() << " ";
9819     }
9820     else if (anArgCase == "-iodtype")
9821     {
9822       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9823       TCollection_AsciiString anValueCase (anArgValue);
9824       anValueCase.LowerCase();
9825       if (anValueCase == "abs"
9826        || anValueCase == "absolute")
9827       {
9828         ++anArgIter;
9829         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9830         continue;
9831       }
9832       else if (anValueCase == "rel"
9833             || anValueCase == "relative")
9834       {
9835         ++anArgIter;
9836         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9837         continue;
9838       }
9839       else if (*anArgValue != '-')
9840       {
9841         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9842         return 1;
9843       }
9844       switch (aCamera->GetIODType())
9845       {
9846         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9847         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9848       }
9849     }
9850     else if (anArgCase == "-zfocus")
9851     {
9852       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9853       if (anArgValue != NULL
9854       && *anArgValue != '-')
9855       {
9856         ++anArgIter;
9857         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9858         continue;
9859       }
9860       theDI << aCamera->ZFocus() << " ";
9861     }
9862     else if (anArgCase == "-zfocustype")
9863     {
9864       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9865       TCollection_AsciiString anValueCase (anArgValue);
9866       anValueCase.LowerCase();
9867       if (anValueCase == "abs"
9868        || anValueCase == "absolute")
9869       {
9870         ++anArgIter;
9871         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9872         continue;
9873       }
9874       else if (anValueCase == "rel"
9875             || anValueCase == "relative")
9876       {
9877         ++anArgIter;
9878         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9879         continue;
9880       }
9881       else if (*anArgValue != '-')
9882       {
9883         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9884         return 1;
9885       }
9886       switch (aCamera->ZFocusType())
9887       {
9888         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9889         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9890       }
9891     }
9892     else if (anArgCase == "-fov"
9893           || anArgCase == "-fovy")
9894     {
9895       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9896       if (anArgValue != NULL
9897       && *anArgValue != '-')
9898       {
9899         ++anArgIter;
9900         aCamera->SetFOVy (Draw::Atof (anArgValue));
9901         continue;
9902       }
9903       theDI << aCamera->FOVy() << " ";
9904     }
9905     else if (aPrsName.IsEmpty()
9906          && !anArgCase.StartsWith ("-"))
9907     {
9908       aPrsName = anArg;
9909     }
9910     else
9911     {
9912       std::cout << "Error: unknown argument '" << anArg << "'\n";
9913       return 1;
9914     }
9915   }
9916
9917   if (aPrsName.IsEmpty()
9918    || theArgsNb > 2)
9919   {
9920     aView->AutoZFit();
9921     aView->Redraw();
9922   }
9923
9924   if (!aPrsName.IsEmpty())
9925   {
9926     Handle(AIS_CameraFrustum) aCameraFrustum;
9927     if (GetMapOfAIS().IsBound2 (aPrsName))
9928     {
9929       // find existing object
9930       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9931       if (aCameraFrustum.IsNull())
9932       {
9933         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
9934         return 1;
9935       }
9936     }
9937
9938     if (aCameraFrustum.IsNull())
9939     {
9940       aCameraFrustum = new AIS_CameraFrustum();
9941     }
9942     else
9943     {
9944       // not include displayed object of old camera frustum in the new one.
9945       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9946       aView->ZFitAll();
9947     }
9948     aCameraFrustum->SetCameraFrustum (aView->Camera());
9949
9950     ViewerTest::Display (aPrsName, aCameraFrustum);
9951   }
9952
9953   return 0;
9954 }
9955
9956 //! Parse stereo output mode
9957 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9958                                          Graphic3d_StereoMode& theMode)
9959 {
9960   TCollection_AsciiString aFlag (theArg);
9961   aFlag.LowerCase();
9962   if (aFlag == "quadbuffer")
9963   {
9964     theMode = Graphic3d_StereoMode_QuadBuffer;
9965   }
9966   else if (aFlag == "anaglyph")
9967   {
9968     theMode = Graphic3d_StereoMode_Anaglyph;
9969   }
9970   else if (aFlag == "row"
9971         || aFlag == "rowinterlaced")
9972   {
9973     theMode = Graphic3d_StereoMode_RowInterlaced;
9974   }
9975   else if (aFlag == "col"
9976         || aFlag == "colinterlaced"
9977         || aFlag == "columninterlaced")
9978   {
9979     theMode = Graphic3d_StereoMode_ColumnInterlaced;
9980   }
9981   else if (aFlag == "chess"
9982         || aFlag == "chessboard")
9983   {
9984     theMode = Graphic3d_StereoMode_ChessBoard;
9985   }
9986   else if (aFlag == "sbs"
9987         || aFlag == "sidebyside")
9988   {
9989     theMode = Graphic3d_StereoMode_SideBySide;
9990   }
9991   else if (aFlag == "ou"
9992         || aFlag == "overunder")
9993   {
9994     theMode = Graphic3d_StereoMode_OverUnder;
9995   }
9996   else if (aFlag == "pageflip"
9997         || aFlag == "softpageflip")
9998   {
9999     theMode = Graphic3d_StereoMode_SoftPageFlip;
10000   }
10001   else
10002   {
10003     return Standard_False;
10004   }
10005   return Standard_True;
10006 }
10007
10008 //! Parse anaglyph filter
10009 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10010                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10011 {
10012   TCollection_AsciiString aFlag (theArg);
10013   aFlag.LowerCase();
10014   if (aFlag == "redcyansimple")
10015   {
10016     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10017   }
10018   else if (aFlag == "redcyan"
10019         || aFlag == "redcyanoptimized")
10020   {
10021     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10022   }
10023   else if (aFlag == "yellowbluesimple")
10024   {
10025     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10026   }
10027   else if (aFlag == "yellowblue"
10028         || aFlag == "yellowblueoptimized")
10029   {
10030     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10031   }
10032   else if (aFlag == "greenmagenta"
10033         || aFlag == "greenmagentasimple")
10034   {
10035     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10036   }
10037   else
10038   {
10039     return Standard_False;
10040   }
10041   return Standard_True;
10042 }
10043
10044 //==============================================================================
10045 //function : VStereo
10046 //purpose  :
10047 //==============================================================================
10048
10049 static int VStereo (Draw_Interpretor& theDI,
10050                     Standard_Integer  theArgNb,
10051                     const char**      theArgVec)
10052 {
10053   Handle(V3d_View) aView = ViewerTest::CurrentView();
10054   if (theArgNb < 2)
10055   {
10056     if (aView.IsNull())
10057     {
10058       std::cout << "Error: no active viewer!\n";
10059       return 0;
10060     }
10061
10062     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10063     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10064     if (isActive)
10065     {
10066       TCollection_AsciiString aMode;
10067       switch (aView->RenderingParams().StereoMode)
10068       {
10069         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10070         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10071         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10072         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10073         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10074         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10075         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10076         case Graphic3d_StereoMode_Anaglyph  :
10077           aMode = "anaglyph";
10078           switch (aView->RenderingParams().AnaglyphFilter)
10079           {
10080             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10081             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10082             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10083             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10084             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10085             default: break;
10086           }
10087         default: break;
10088       }
10089       theDI << "Mode " << aMode << "\n";
10090     }
10091     return 0;
10092   }
10093
10094   Handle(Graphic3d_Camera) aCamera;
10095   Graphic3d_RenderingParams*   aParams   = NULL;
10096   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10097   if (!aView.IsNull())
10098   {
10099     aParams   = &aView->ChangeRenderingParams();
10100     aMode     = aParams->StereoMode;
10101     aCamera   = aView->Camera();
10102   }
10103
10104   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10105   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10106   {
10107     Standard_CString        anArg = theArgVec[anArgIter];
10108     TCollection_AsciiString aFlag (anArg);
10109     aFlag.LowerCase();
10110     if (anUpdateTool.parseRedrawMode (aFlag))
10111     {
10112       continue;
10113     }
10114     else if (aFlag == "0"
10115           || aFlag == "off")
10116     {
10117       if (++anArgIter < theArgNb)
10118       {
10119         std::cout << "Error: wrong number of arguments!\n";
10120         return 1;
10121       }
10122
10123       if (!aCamera.IsNull()
10124        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10125       {
10126         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10127       }
10128       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10129       return 0;
10130     }
10131     else if (aFlag == "1"
10132           || aFlag == "on")
10133     {
10134       if (++anArgIter < theArgNb)
10135       {
10136         std::cout << "Error: wrong number of arguments!\n";
10137         return 1;
10138       }
10139
10140       if (!aCamera.IsNull())
10141       {
10142         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10143       }
10144       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10145       return 0;
10146     }
10147     else if (aFlag == "-reverse"
10148           || aFlag == "-reversed"
10149           || aFlag == "-swap")
10150     {
10151       Standard_Boolean toEnable = Standard_True;
10152       if (++anArgIter < theArgNb
10153       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10154       {
10155         --anArgIter;
10156       }
10157       aParams->ToReverseStereo = toEnable;
10158     }
10159     else if (aFlag == "-noreverse"
10160           || aFlag == "-noswap")
10161     {
10162       Standard_Boolean toDisable = Standard_True;
10163       if (++anArgIter < theArgNb
10164       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10165       {
10166         --anArgIter;
10167       }
10168       aParams->ToReverseStereo = !toDisable;
10169     }
10170     else if (aFlag == "-mode"
10171           || aFlag == "-stereomode")
10172     {
10173       if (++anArgIter >= theArgNb
10174       || !parseStereoMode (theArgVec[anArgIter], aMode))
10175       {
10176         std::cout << "Error: syntax error at '" << anArg << "'\n";
10177         return 1;
10178       }
10179
10180       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10181       {
10182         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10183       }
10184     }
10185     else if (aFlag == "-anaglyph"
10186           || aFlag == "-anaglyphfilter")
10187     {
10188       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10189       if (++anArgIter >= theArgNb
10190       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10191       {
10192         std::cout << "Error: syntax error at '" << anArg << "'\n";
10193         return 1;
10194       }
10195
10196       aMode = Graphic3d_StereoMode_Anaglyph;
10197       aParams->AnaglyphFilter = aFilter;
10198     }
10199     else if (parseStereoMode (anArg, aMode)) // short syntax
10200     {
10201       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10202       {
10203         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10204       }
10205     }
10206     else
10207     {
10208       std::cout << "Error: syntax error at '" << anArg << "'\n";
10209       return 1;
10210     }
10211   }
10212
10213   if (!aView.IsNull())
10214   {
10215     aParams->StereoMode = aMode;
10216     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10217   }
10218   return 0;
10219 }
10220
10221 //===============================================================================================
10222 //function : VDefaults
10223 //purpose  :
10224 //===============================================================================================
10225 static int VDefaults (Draw_Interpretor& theDi,
10226                       Standard_Integer  theArgsNb,
10227                       const char**      theArgVec)
10228 {
10229   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10230   if (aCtx.IsNull())
10231   {
10232     std::cerr << "No active viewer!\n";
10233     return 1;
10234   }
10235
10236   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10237   if (theArgsNb < 2)
10238   {
10239     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10240     {
10241       theDi << "DeflType:           relative\n"
10242             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10243     }
10244     else
10245     {
10246       theDi << "DeflType:           absolute\n"
10247             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10248     }
10249     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10250     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10251     return 0;
10252   }
10253
10254   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10255   {
10256     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10257     anArg.UpperCase();
10258     if (anArg == "-ABSDEFL"
10259      || anArg == "-ABSOLUTEDEFLECTION"
10260      || anArg == "-DEFL"
10261      || anArg == "-DEFLECTION")
10262     {
10263       if (++anArgIter >= theArgsNb)
10264       {
10265         std::cout << "Error: wrong syntax at " << anArg << "\n";
10266         return 1;
10267       }
10268       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10269       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10270     }
10271     else if (anArg == "-RELDEFL"
10272           || anArg == "-RELATIVEDEFLECTION"
10273           || anArg == "-DEVCOEFF"
10274           || anArg == "-DEVIATIONCOEFF"
10275           || anArg == "-DEVIATIONCOEFFICIENT")
10276     {
10277       if (++anArgIter >= theArgsNb)
10278       {
10279         std::cout << "Error: wrong syntax at " << anArg << "\n";
10280         return 1;
10281       }
10282       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10283       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10284     }
10285     else if (anArg == "-ANGDEFL"
10286           || anArg == "-ANGULARDEFL"
10287           || anArg == "-ANGULARDEFLECTION")
10288     {
10289       if (++anArgIter >= theArgsNb)
10290       {
10291         std::cout << "Error: wrong syntax at " << anArg << "\n";
10292         return 1;
10293       }
10294       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10295       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10296     }
10297     else if (anArg == "-AUTOTR"
10298           || anArg == "-AUTOTRIANG"
10299           || anArg == "-AUTOTRIANGULATION")
10300     {
10301       if (++anArgIter >= theArgsNb)
10302       {
10303         std::cout << "Error: wrong syntax at " << anArg << "\n";
10304         return 1;
10305       }
10306       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10307       aValue.LowerCase();
10308       if (aValue == "on"
10309        || aValue == "1")
10310       {
10311         aDefParams->SetAutoTriangulation (Standard_True);
10312       }
10313       else if (aValue == "off"
10314             || aValue == "0")
10315       {
10316         aDefParams->SetAutoTriangulation (Standard_False);
10317       }
10318     }
10319     else
10320     {
10321       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10322     }
10323   }
10324
10325   return 0;
10326 }
10327
10328 //! Auxiliary method
10329 inline void addLight (const Handle(V3d_Light)& theLightNew,
10330                       const Graphic3d_ZLayerId theLayer,
10331                       const Standard_Boolean   theIsGlobal)
10332 {
10333   if (theLightNew.IsNull())
10334   {
10335     return;
10336   }
10337
10338   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10339   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10340   {
10341     aViewer->AddLight (theLightNew);
10342     if (theIsGlobal)
10343     {
10344       aViewer->SetLightOn (theLightNew);
10345     }
10346     else
10347     {
10348       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10349     }
10350   }
10351   else
10352   {
10353     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10354     if (aSettings.Lights().IsNull())
10355     {
10356       aSettings.SetLights (new Graphic3d_LightSet());
10357     }
10358     aSettings.Lights()->Add (theLightNew);
10359     aViewer->SetZLayerSettings (theLayer, aSettings);
10360   }
10361 }
10362
10363 //! Auxiliary method
10364 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10365 {
10366   TCollection_AsciiString anArgNextCase (theArgNext);
10367   anArgNextCase.UpperCase();
10368   if (anArgNextCase.Length() > 5
10369    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10370   {
10371     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10372   }
10373   else
10374   {
10375     return theArgNext.IntegerValue();
10376   }
10377 }
10378
10379 //===============================================================================================
10380 //function : VLight
10381 //purpose  :
10382 //===============================================================================================
10383 static int VLight (Draw_Interpretor& theDi,
10384                    Standard_Integer  theArgsNb,
10385                    const char**      theArgVec)
10386 {
10387   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10388   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10389   if (aView.IsNull()
10390    || aViewer.IsNull())
10391   {
10392     std::cerr << "No active viewer!\n";
10393     return 1;
10394   }
10395
10396   Standard_Real anXYZ[3]   = {};
10397   Standard_Real anAtten[2] = {};
10398   if (theArgsNb < 2)
10399   {
10400     // print lights info
10401     Standard_Integer aLightId = 0;
10402     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10403     {
10404       Handle(V3d_Light) aLight = aLightIter.Value();
10405       const Quantity_Color aColor = aLight->Color();
10406       theDi << "Light #" << aLightId
10407             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10408             << " [" << aLight->GetId() << "]" << "\n";
10409       switch (aLight->Type())
10410       {
10411         case V3d_AMBIENT:
10412         {
10413           theDi << "  Type:       Ambient\n";
10414           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10415           break;
10416         }
10417         case V3d_DIRECTIONAL:
10418         {
10419           theDi << "  Type:       Directional\n";
10420           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10421           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10422           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10423           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10424           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10425           break;
10426         }
10427         case V3d_POSITIONAL:
10428         {
10429           theDi << "  Type:       Positional\n";
10430           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10431           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10432           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10433           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10434           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10435           aLight->Attenuation (anAtten[0], anAtten[1]);
10436           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10437           break;
10438         }
10439         case V3d_SPOT:
10440         {
10441           theDi << "  Type:       Spot\n";
10442           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10443           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10444           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10445           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10446           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10447           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10448           aLight->Attenuation (anAtten[0], anAtten[1]);
10449           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10450           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10451           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10452           break;
10453         }
10454         default:
10455         {
10456           theDi << "  Type:       UNKNOWN\n";
10457           break;
10458         }
10459       }
10460       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10461     }
10462   }
10463
10464   Handle(V3d_Light) aLightNew;
10465   Handle(V3d_Light) aLightOld;
10466   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10467   Standard_Boolean  isGlobal = Standard_True;
10468   Standard_Boolean  toCreate = Standard_False;
10469   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10470   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10471   {
10472     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10473
10474     TCollection_AsciiString aName, aValue;
10475     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10476     TCollection_AsciiString anArgCase (anArg);
10477     anArgCase.UpperCase();
10478     if (anUpdateTool.parseRedrawMode (anArg))
10479     {
10480       continue;
10481     }
10482
10483     if (anArgCase.IsEqual ("NEW")
10484      || anArgCase.IsEqual ("ADD")
10485      || anArgCase.IsEqual ("CREATE")
10486      || anArgCase.IsEqual ("-NEW")
10487      || anArgCase.IsEqual ("-ADD")
10488      || anArgCase.IsEqual ("-CREATE"))
10489     {
10490       toCreate = Standard_True;
10491     }
10492     else if (anArgCase.IsEqual ("-LAYER")
10493           || anArgCase.IsEqual ("-ZLAYER"))
10494     {
10495       if (++anArgIt >= theArgsNb)
10496       {
10497         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10498         return 1;
10499       }
10500
10501       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10502       aValStr.LowerCase();
10503       if (aValStr == "default"
10504        || aValStr == "def")
10505       {
10506         aLayer = Graphic3d_ZLayerId_Default;
10507       }
10508       else if (aValStr == "top")
10509       {
10510         aLayer = Graphic3d_ZLayerId_Top;
10511       }
10512       else if (aValStr == "topmost")
10513       {
10514         aLayer = Graphic3d_ZLayerId_Topmost;
10515       }
10516       else if (aValStr == "toposd"
10517             || aValStr == "osd")
10518       {
10519         aLayer = Graphic3d_ZLayerId_TopOSD;
10520       }
10521       else if (aValStr == "botosd"
10522             || aValStr == "bottom")
10523       {
10524         aLayer = Graphic3d_ZLayerId_BotOSD;
10525       }
10526       else if (aValStr.IsIntegerValue())
10527       {
10528         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10529       }
10530       else
10531       {
10532         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10533         return 1;
10534       }
10535     }
10536     else if (anArgCase.IsEqual ("GLOB")
10537           || anArgCase.IsEqual ("GLOBAL")
10538           || anArgCase.IsEqual ("-GLOB")
10539           || anArgCase.IsEqual ("-GLOBAL"))
10540     {
10541       isGlobal = Standard_True;
10542     }
10543     else if (anArgCase.IsEqual ("LOC")
10544           || anArgCase.IsEqual ("LOCAL")
10545           || anArgCase.IsEqual ("-LOC")
10546           || anArgCase.IsEqual ("-LOCAL"))
10547     {
10548       isGlobal = Standard_False;
10549     }
10550     else if (anArgCase.IsEqual ("DEF")
10551           || anArgCase.IsEqual ("DEFAULTS")
10552           || anArgCase.IsEqual ("-DEF")
10553           || anArgCase.IsEqual ("-DEFAULTS"))
10554     {
10555       toCreate = Standard_False;
10556       aViewer->SetDefaultLights();
10557     }
10558     else if (anArgCase.IsEqual ("CLR")
10559           || anArgCase.IsEqual ("CLEAR")
10560           || anArgCase.IsEqual ("-CLR")
10561           || anArgCase.IsEqual ("-CLEAR"))
10562     {
10563       toCreate = Standard_False;
10564
10565       TColStd_SequenceOfInteger aLayers;
10566       aViewer->GetAllZLayers (aLayers);
10567       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10568       {
10569         if (aLayeriter.Value() == aLayer
10570          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10571         {
10572           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10573           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10574           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10575           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10576           {
10577             break;
10578           }
10579         }
10580       }
10581
10582       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10583       {
10584         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10585         {
10586           Handle(V3d_Light) aLight = aLightIter.Value();
10587           aViewer->DelLight (aLight);
10588           aLightIter = aView->ActiveLightIterator();
10589         }
10590       }
10591     }
10592     else if (anArgCase.IsEqual ("AMB")
10593           || anArgCase.IsEqual ("AMBIENT")
10594           || anArgCase.IsEqual ("AMBLIGHT"))
10595     {
10596       if (!toCreate)
10597       {
10598         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10599         return 1;
10600       }
10601
10602       addLight (aLightNew, aLayer, isGlobal);
10603       toCreate  = Standard_False;
10604       aLightNew = new V3d_AmbientLight();
10605     }
10606     else if (anArgCase.IsEqual ("DIRECTIONAL")
10607           || anArgCase.IsEqual ("DIRLIGHT"))
10608     {
10609       if (!toCreate)
10610       {
10611         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10612         return 1;
10613       }
10614
10615       addLight (aLightNew, aLayer, isGlobal);
10616       toCreate  = Standard_False;
10617       aLightNew = new V3d_DirectionalLight();
10618     }
10619     else if (anArgCase.IsEqual ("SPOT")
10620           || anArgCase.IsEqual ("SPOTLIGHT"))
10621     {
10622       if (!toCreate)
10623       {
10624         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10625         return 1;
10626       }
10627
10628       addLight (aLightNew, aLayer, isGlobal);
10629       toCreate  = Standard_False;
10630       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10631     }
10632     else if (anArgCase.IsEqual ("POSLIGHT")
10633           || anArgCase.IsEqual ("POSITIONAL"))
10634     {
10635       if (!toCreate)
10636       {
10637         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10638         return 1;
10639       }
10640
10641       addLight (aLightNew, aLayer, isGlobal);
10642       toCreate  = Standard_False;
10643       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10644     }
10645     else if (anArgCase.IsEqual ("CHANGE")
10646           || anArgCase.IsEqual ("-CHANGE"))
10647     {
10648       if (++anArgIt >= theArgsNb)
10649       {
10650         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10651         return 1;
10652       }
10653
10654       addLight (aLightNew, aLayer, isGlobal);
10655       aLightNew.Nullify();
10656       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10657       Standard_Integer aLightIt = 0;
10658       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10659       {
10660         if (aLightIt == aLightId)
10661         {
10662           aLightOld = aLightIter.Value();
10663           break;
10664         }
10665       }
10666
10667       if (aLightOld.IsNull())
10668       {
10669         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10670         return 1;
10671       }
10672     }
10673     else if (anArgCase.IsEqual ("DEL")
10674           || anArgCase.IsEqual ("DELETE")
10675           || anArgCase.IsEqual ("-DEL")
10676           || anArgCase.IsEqual ("-DELETE"))
10677     {
10678       Handle(V3d_Light) aLightDel;
10679       if (++anArgIt >= theArgsNb)
10680       {
10681         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10682         return 1;
10683       }
10684
10685       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10686       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10687       Standard_Integer aLightIt = 0;
10688       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10689       {
10690         aLightDel = aLightIter.Value();
10691         if (aLightIt == aLightDelId)
10692         {
10693           break;
10694         }
10695       }
10696       if (aLightDel.IsNull())
10697       {
10698         continue;
10699       }
10700
10701       TColStd_SequenceOfInteger aLayers;
10702       aViewer->GetAllZLayers (aLayers);
10703       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10704       {
10705         if (aLayeriter.Value() == aLayer
10706          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10707         {
10708           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10709           if (!aSettings.Lights().IsNull())
10710           {
10711             aSettings.Lights()->Remove (aLightDel);
10712             if (aSettings.Lights()->IsEmpty())
10713             {
10714               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10715             }
10716           }
10717           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10718           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10719           {
10720             break;
10721           }
10722         }
10723       }
10724
10725       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10726       {
10727         aViewer->DelLight (aLightDel);
10728       }
10729     }
10730     else if (anArgCase.IsEqual ("COLOR")
10731           || anArgCase.IsEqual ("COLOUR")
10732           || anArgCase.IsEqual ("-COLOR")
10733           || anArgCase.IsEqual ("-COLOUR"))
10734     {
10735       if (++anArgIt >= theArgsNb
10736        || aLightCurr.IsNull())
10737       {
10738         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10739         return 1;
10740       }
10741
10742       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10743       anArgNext.UpperCase();
10744       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10745       aLightCurr->SetColor (aColor);
10746     }
10747     else if (anArgCase.IsEqual ("POS")
10748           || anArgCase.IsEqual ("POSITION")
10749           || anArgCase.IsEqual ("-POS")
10750           || anArgCase.IsEqual ("-POSITION"))
10751     {
10752       if ((anArgIt + 3) >= theArgsNb
10753        || aLightCurr.IsNull()
10754        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10755         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10756       {
10757         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10758         return 1;
10759       }
10760
10761       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10762       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10763       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10764       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
10765     }
10766     else if (anArgCase.IsEqual ("DIR")
10767           || anArgCase.IsEqual ("DIRECTION")
10768           || anArgCase.IsEqual ("-DIR")
10769           || anArgCase.IsEqual ("-DIRECTION"))
10770     {
10771       if ((anArgIt + 3) >= theArgsNb
10772        || aLightCurr.IsNull()
10773        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
10774         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10775       {
10776         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10777         return 1;
10778       }
10779
10780       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10781       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10782       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10783       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
10784     }
10785     else if (anArgCase.IsEqual ("SM")
10786           || anArgCase.IsEqual ("SMOOTHNESS")
10787           || anArgCase.IsEqual ("-SM")
10788           || anArgCase.IsEqual ("-SMOOTHNESS"))
10789     {
10790       if (++anArgIt >= theArgsNb
10791        || aLightCurr.IsNull())
10792       {
10793         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10794         return 1;
10795       }
10796
10797       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10798       if (Abs (aSmoothness) <= ShortRealEpsilon())
10799       {
10800         aLightCurr->SetIntensity (1.f);
10801       }
10802       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
10803       {
10804         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
10805       }
10806       else
10807       {
10808         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
10809         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
10810       }
10811
10812       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
10813       {
10814         aLightCurr->SetSmoothRadius (aSmoothness);
10815       }
10816       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
10817       {
10818         aLightCurr->SetSmoothAngle (aSmoothness);
10819       }
10820     }
10821     else if (anArgCase.IsEqual ("INT")
10822           || anArgCase.IsEqual ("INTENSITY")
10823           || anArgCase.IsEqual ("-INT")
10824           || anArgCase.IsEqual ("-INTENSITY"))
10825     {
10826       if (++anArgIt >= theArgsNb
10827        || aLightCurr.IsNull())
10828       {
10829         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10830         return 1;
10831       }
10832
10833       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10834       aLightCurr->SetIntensity (aIntensity);
10835     }
10836     else if (anArgCase.IsEqual ("ANG")
10837           || anArgCase.IsEqual ("ANGLE")
10838           || anArgCase.IsEqual ("-ANG")
10839           || anArgCase.IsEqual ("-ANGLE"))
10840     {
10841       if (++anArgIt >= theArgsNb
10842        || aLightCurr.IsNull()
10843        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10844       {
10845         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10846         return 1;
10847       }
10848
10849       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10850       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
10851     }
10852     else if (anArgCase.IsEqual ("CONSTATTEN")
10853           || anArgCase.IsEqual ("CONSTATTENUATION")
10854           || anArgCase.IsEqual ("-CONSTATTEN")
10855           || anArgCase.IsEqual ("-CONSTATTENUATION"))
10856     {
10857       if (++anArgIt >= theArgsNb
10858        || aLightCurr.IsNull()
10859        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10860         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10861       {
10862         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10863         return 1;
10864       }
10865
10866       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10867       anAtten[0] = Atof (theArgVec[anArgIt]);
10868       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10869     }
10870     else if (anArgCase.IsEqual ("LINATTEN")
10871           || anArgCase.IsEqual ("LINEARATTEN")
10872           || anArgCase.IsEqual ("LINEARATTENUATION")
10873           || anArgCase.IsEqual ("-LINATTEN")
10874           || anArgCase.IsEqual ("-LINEARATTEN")
10875           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10876     {
10877       if (++anArgIt >= theArgsNb
10878        || aLightCurr.IsNull()
10879        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10880         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10881       {
10882         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10883         return 1;
10884       }
10885
10886       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10887       anAtten[1] = Atof (theArgVec[anArgIt]);
10888       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10889     }
10890     else if (anArgCase.IsEqual ("EXP")
10891           || anArgCase.IsEqual ("EXPONENT")
10892           || anArgCase.IsEqual ("SPOTEXP")
10893           || anArgCase.IsEqual ("SPOTEXPONENT")
10894           || anArgCase.IsEqual ("-EXP")
10895           || anArgCase.IsEqual ("-EXPONENT")
10896           || anArgCase.IsEqual ("-SPOTEXP")
10897           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10898     {
10899       if (++anArgIt >= theArgsNb
10900        || aLightCurr.IsNull()
10901        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10902       {
10903         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10904         return 1;
10905       }
10906
10907       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10908     }
10909     else if (anArgCase.IsEqual ("HEAD")
10910           || anArgCase.IsEqual ("HEADLIGHT")
10911           || anArgCase.IsEqual ("-HEAD")
10912           || anArgCase.IsEqual ("-HEADLIGHT"))
10913     {
10914       if (aLightCurr.IsNull()
10915        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10916       {
10917         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10918         return 1;
10919       }
10920
10921       Standard_Boolean isHeadLight = Standard_True;
10922       if (anArgIt + 1 < theArgsNb
10923        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10924       {
10925         ++anArgIt;
10926       }
10927       aLightCurr->SetHeadlight (isHeadLight);
10928     }
10929     else
10930     {
10931       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10932     }
10933   }
10934
10935   addLight (aLightNew, aLayer, isGlobal);
10936   return 0;
10937 }
10938
10939 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10940 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10941                                             Standard_Boolean& theToReset,
10942                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10943                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10944 {
10945   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10946   TCollection_AsciiString aVal = theValue;
10947   Standard_Boolean toReverse = Standard_False;
10948   if (aVal == "none")
10949   {
10950     theToReset = Standard_True;
10951     return Standard_True;
10952   }
10953   else if (aVal.StartsWith ("-"))
10954   {
10955     toReverse = Standard_True;
10956     aVal = aVal.SubString (2, aVal.Length());
10957   }
10958   else if (aVal.StartsWith ("no"))
10959   {
10960     toReverse = Standard_True;
10961     aVal = aVal.SubString (3, aVal.Length());
10962   }
10963   else if (aVal.StartsWith ("+"))
10964   {
10965     aVal = aVal.SubString (2, aVal.Length());
10966   }
10967   else
10968   {
10969     theToReset = Standard_True;
10970   }
10971
10972   if (     aVal == "fps"
10973         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
10974   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
10975   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
10976   else if (aVal == "structs"
10977         || aVal == "structures"
10978         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
10979   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
10980   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
10981   else if (aVal == "tris"
10982         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
10983   else if (aVal == "pnts"
10984         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
10985   else if (aVal == "mem"
10986         || aVal == "gpumem"
10987         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
10988   else if (aVal == "skipimmediate"
10989         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
10990   else if (aVal == "frametime"
10991         || aVal == "frametimers"
10992         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
10993   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
10994   else if (aVal == "extended"
10995         || aVal == "verbose"
10996         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
10997   else if (aVal == "full"
10998         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
10999   else
11000   {
11001     return Standard_False;
11002   }
11003
11004   if (toReverse)
11005   {
11006     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11007   }
11008   else
11009   {
11010     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11011   }
11012   return Standard_True;
11013 }
11014
11015 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11016 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11017                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11018 {
11019   TCollection_AsciiString aValue = theValue;
11020   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11021   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11022   Standard_Boolean toReset = Standard_False;
11023   for (;;)
11024   {
11025     Standard_Integer aSplitPos = aValue.Search ("|");
11026     if (aSplitPos <= 0)
11027     {
11028       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11029       {
11030         return Standard_False;
11031       }
11032       if (toReset)
11033       {
11034         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11035       }
11036       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11037       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11038       return Standard_True;
11039     }
11040
11041     if (aSplitPos > 1)
11042     {
11043       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11044       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11045       {
11046         return Standard_False;
11047       }
11048     }
11049     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11050   }
11051 }
11052
11053 //=======================================================================
11054 //function : VRenderParams
11055 //purpose  : Enables/disables rendering features
11056 //=======================================================================
11057
11058 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11059                                        Standard_Integer  theArgNb,
11060                                        const char**      theArgVec)
11061 {
11062   Handle(V3d_View) aView = ViewerTest::CurrentView();
11063   if (aView.IsNull())
11064   {
11065     std::cerr << "Error: no active viewer!\n";
11066     return 1;
11067   }
11068
11069   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11070   TCollection_AsciiString aCmdName (theArgVec[0]);
11071   aCmdName.LowerCase();
11072   if (aCmdName == "vraytrace")
11073   {
11074     if (theArgNb == 1)
11075     {
11076       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11077       return 0;
11078     }
11079     else if (theArgNb == 2)
11080     {
11081       TCollection_AsciiString aValue (theArgVec[1]);
11082       aValue.LowerCase();
11083       if (aValue == "on"
11084        || aValue == "1")
11085       {
11086         aParams.Method = Graphic3d_RM_RAYTRACING;
11087         aView->Redraw();
11088         return 0;
11089       }
11090       else if (aValue == "off"
11091             || aValue == "0")
11092       {
11093         aParams.Method = Graphic3d_RM_RASTERIZATION;
11094         aView->Redraw();
11095         return 0;
11096       }
11097       else
11098       {
11099         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11100         return 1;
11101       }
11102     }
11103     else
11104     {
11105       std::cout << "Error: wrong number of arguments\n";
11106       return 1;
11107     }
11108   }
11109
11110   if (theArgNb < 2)
11111   {
11112     theDI << "renderMode:  ";
11113     switch (aParams.Method)
11114     {
11115       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11116       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11117     }
11118     theDI << "\n";
11119     theDI << "transparency:  ";
11120     switch (aParams.TransparencyMethod)
11121     {
11122       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11123       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11124                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11125     }
11126     theDI << "\n";
11127     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11128     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11129     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11130     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11131     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11132     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11133     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11134     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11135     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11136     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11137     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11138     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11139     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11140     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11141     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11142     theDI << "shadingModel: ";
11143     switch (aView->ShadingModel())
11144     {
11145       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11146       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11147       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11148       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11149       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11150     }
11151     {
11152       theDI << "perfCounters:";
11153       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11154       {
11155         theDI << " fps";
11156       }
11157       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11158       {
11159         theDI << " cpu";
11160       }
11161       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11162       {
11163         theDI << " structs";
11164       }
11165       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11166       {
11167         theDI << " groups";
11168       }
11169       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11170       {
11171         theDI << " arrays";
11172       }
11173       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11174       {
11175         theDI << " tris";
11176       }
11177       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11178       {
11179         theDI << " pnts";
11180       }
11181       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11182       {
11183         theDI << " gpumem";
11184       }
11185       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11186       {
11187         theDI << " frameTime";
11188       }
11189       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11190       {
11191         theDI << " skipimmediate";
11192       }
11193       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11194       {
11195         theDI << " none";
11196       }
11197       theDI << "\n";
11198     }
11199     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11200     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11201     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11202                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11203                                                                                                                     "noUpdate") << "\n";
11204     theDI << "\n";
11205     return 0;
11206   }
11207
11208   Standard_Boolean toPrint = Standard_False;
11209   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11210   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11211   {
11212     Standard_CString        anArg (theArgVec[anArgIter]);
11213     TCollection_AsciiString aFlag (anArg);
11214     aFlag.LowerCase();
11215     if (anUpdateTool.parseRedrawMode (aFlag))
11216     {
11217       continue;
11218     }
11219     else if (aFlag == "-echo"
11220           || aFlag == "-print")
11221     {
11222       toPrint = Standard_True;
11223       anUpdateTool.Invalidate();
11224     }
11225     else if (aFlag == "-mode"
11226           || aFlag == "-rendermode"
11227           || aFlag == "-render_mode")
11228     {
11229       if (toPrint)
11230       {
11231         switch (aParams.Method)
11232         {
11233           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11234           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11235         }
11236         continue;
11237       }
11238       else
11239       {
11240         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11241         return 1;
11242       }
11243     }
11244     else if (aFlag == "-ray"
11245           || aFlag == "-raytrace")
11246     {
11247       if (toPrint)
11248       {
11249         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11250         continue;
11251       }
11252
11253       aParams.Method = Graphic3d_RM_RAYTRACING;
11254     }
11255     else if (aFlag == "-rast"
11256           || aFlag == "-raster"
11257           || aFlag == "-rasterization")
11258     {
11259       if (toPrint)
11260       {
11261         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11262         continue;
11263       }
11264
11265       aParams.Method = Graphic3d_RM_RASTERIZATION;
11266     }
11267     else if (aFlag == "-msaa")
11268     {
11269       if (toPrint)
11270       {
11271         theDI << aParams.NbMsaaSamples << " ";
11272         continue;
11273       }
11274       else if (++anArgIter >= theArgNb)
11275       {
11276         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11277         return 1;
11278       }
11279
11280       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11281       if (aNbSamples < 0)
11282       {
11283         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11284         return 1;
11285       }
11286       else
11287       {
11288         aParams.NbMsaaSamples = aNbSamples;
11289       }
11290     }
11291     else if (aFlag == "-linefeather"
11292           || aFlag == "-edgefeather"
11293           || aFlag == "-feather")
11294     {
11295       if (toPrint)
11296       {
11297         theDI << " " << aParams.LineFeather << " ";
11298         continue;
11299       }
11300       else if (++anArgIter >= theArgNb)
11301       {
11302         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11303         return 1;
11304       }
11305
11306       TCollection_AsciiString aParam = theArgVec[anArgIter];
11307       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11308       if (aFeather <= 0.0f)
11309       {
11310         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11311         return 1;
11312       }
11313       aParams.LineFeather = aFeather;
11314     }
11315     else if (aFlag == "-oit")
11316     {
11317       if (toPrint)
11318       {
11319         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11320         {
11321           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11322         }
11323         else
11324         {
11325           theDI << "off" << " ";
11326         }
11327         continue;
11328       }
11329       else if (++anArgIter >= theArgNb)
11330       {
11331         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11332         return 1;
11333       }
11334
11335       TCollection_AsciiString aParam = theArgVec[anArgIter];
11336       aParam.LowerCase();
11337       if (aParam.IsRealValue())
11338       {
11339         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11340         if (aWeight < 0.f || aWeight > 1.f)
11341         {
11342           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11343           return 1;
11344         }
11345
11346         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11347         aParams.OitDepthFactor     = aWeight;
11348       }
11349       else if (aParam == "off")
11350       {
11351         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11352       }
11353       else
11354       {
11355         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11356         return 1;
11357       }
11358     }
11359     else if (aFlag == "-depthprepass")
11360     {
11361       if (toPrint)
11362       {
11363         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11364         continue;
11365       }
11366       aParams.ToEnableDepthPrepass = Standard_True;
11367       if (anArgIter + 1 < theArgNb
11368        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11369       {
11370         ++anArgIter;
11371       }
11372     }
11373     else if (aFlag == "-samplealphatocoverage"
11374           || aFlag == "-alphatocoverage")
11375     {
11376       if (toPrint)
11377       {
11378         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11379         continue;
11380       }
11381       aParams.ToEnableAlphaToCoverage = Standard_True;
11382       if (anArgIter + 1 < theArgNb
11383        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11384       {
11385         ++anArgIter;
11386       }
11387     }
11388     else if (aFlag == "-rendscale"
11389           || aFlag == "-renderscale"
11390           || aFlag == "-renderresolutionscale")
11391     {
11392       if (toPrint)
11393       {
11394         theDI << aParams.RenderResolutionScale << " ";
11395         continue;
11396       }
11397       else if (++anArgIter >= theArgNb)
11398       {
11399         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11400         return 1;
11401       }
11402
11403       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11404       if (aScale < 0.01)
11405       {
11406         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11407         return 1;
11408       }
11409       else
11410       {
11411         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11412       }
11413     }
11414     else if (aFlag == "-raydepth"
11415           || aFlag == "-ray_depth")
11416     {
11417       if (toPrint)
11418       {
11419         theDI << aParams.RaytracingDepth << " ";
11420         continue;
11421       }
11422       else if (++anArgIter >= theArgNb)
11423       {
11424         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11425         return 1;
11426       }
11427
11428       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11429
11430       // We allow RaytracingDepth be more than 10 in case of GI enabled
11431       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11432       {
11433         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11434         return 1;
11435       }
11436       else
11437       {
11438         aParams.RaytracingDepth = aDepth;
11439       }
11440     }
11441     else if (aFlag == "-shad"
11442           || aFlag == "-shadows")
11443     {
11444       if (toPrint)
11445       {
11446         theDI << (aParams.IsShadowEnabled ? "on" : "off") << " ";
11447         continue;
11448       }
11449
11450       Standard_Boolean toEnable = Standard_True;
11451       if (++anArgIter < theArgNb
11452       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11453       {
11454         --anArgIter;
11455       }
11456       aParams.IsShadowEnabled = toEnable;
11457     }
11458     else if (aFlag == "-refl"
11459           || aFlag == "-reflections")
11460     {
11461       if (toPrint)
11462       {
11463         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11464         continue;
11465       }
11466
11467       Standard_Boolean toEnable = Standard_True;
11468       if (++anArgIter < theArgNb
11469       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11470       {
11471         --anArgIter;
11472       }
11473       aParams.IsReflectionEnabled = toEnable;
11474     }
11475     else if (aFlag == "-fsaa")
11476     {
11477       if (toPrint)
11478       {
11479         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11480         continue;
11481       }
11482
11483       Standard_Boolean toEnable = Standard_True;
11484       if (++anArgIter < theArgNb
11485       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11486       {
11487         --anArgIter;
11488       }
11489       aParams.IsAntialiasingEnabled = toEnable;
11490     }
11491     else if (aFlag == "-gleam")
11492     {
11493       if (toPrint)
11494       {
11495         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11496         continue;
11497       }
11498
11499       Standard_Boolean toEnable = Standard_True;
11500       if (++anArgIter < theArgNb
11501       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11502       {
11503         --anArgIter;
11504       }
11505       aParams.IsTransparentShadowEnabled = toEnable;
11506     }
11507     else if (aFlag == "-gi")
11508     {
11509       if (toPrint)
11510       {
11511         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11512         continue;
11513       }
11514
11515       Standard_Boolean toEnable = Standard_True;
11516       if (++anArgIter < theArgNb
11517       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11518       {
11519         --anArgIter;
11520       }
11521       aParams.IsGlobalIlluminationEnabled = toEnable;
11522       if (!toEnable)
11523       {
11524         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11525       }
11526     }
11527     else if (aFlag == "-blockedrng"
11528           || aFlag == "-brng")
11529     {
11530       if (toPrint)
11531       {
11532         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11533         continue;
11534       }
11535
11536       Standard_Boolean toEnable = Standard_True;
11537       if (++anArgIter < theArgNb
11538         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11539       {
11540         --anArgIter;
11541       }
11542       aParams.CoherentPathTracingMode = toEnable;
11543     }
11544     else if (aFlag == "-maxrad")
11545     {
11546       if (toPrint)
11547       {
11548         theDI << aParams.RadianceClampingValue << " ";
11549         continue;
11550       }
11551       else if (++anArgIter >= theArgNb)
11552       {
11553         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11554         return 1;
11555       }
11556
11557       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11558       if (!aMaxRadStr.IsRealValue())
11559       {
11560         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11561         return 1;
11562       }
11563
11564       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11565       if (aMaxRadiance <= 0.0)
11566       {
11567         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11568         return 1;
11569       }
11570       else
11571       {
11572         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11573       }
11574     }
11575     else if (aFlag == "-iss")
11576     {
11577       if (toPrint)
11578       {
11579         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11580         continue;
11581       }
11582
11583       Standard_Boolean toEnable = Standard_True;
11584       if (++anArgIter < theArgNb
11585         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11586       {
11587         --anArgIter;
11588       }
11589       aParams.AdaptiveScreenSampling = toEnable;
11590     }
11591     else if (aFlag == "-issatomic")
11592     {
11593       if (toPrint)
11594       {
11595         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11596         continue;
11597       }
11598
11599       Standard_Boolean toEnable = Standard_True;
11600       if (++anArgIter < theArgNb
11601       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11602       {
11603         --anArgIter;
11604       }
11605       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11606     }
11607     else if (aFlag == "-issd")
11608     {
11609       if (toPrint)
11610       {
11611         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11612         continue;
11613       }
11614
11615       Standard_Boolean toEnable = Standard_True;
11616       if (++anArgIter < theArgNb
11617         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11618       {
11619         --anArgIter;
11620       }
11621       aParams.ShowSamplingTiles = toEnable;
11622     }
11623     else if (aFlag == "-tilesize")
11624     {
11625       if (toPrint)
11626       {
11627         theDI << aParams.RayTracingTileSize << " ";
11628         continue;
11629       }
11630       else if (++anArgIter >= theArgNb)
11631       {
11632         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11633         return 1;
11634       }
11635
11636       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11637       if (aTileSize < 1)
11638       {
11639         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11640         return 1;
11641       }
11642       aParams.RayTracingTileSize = aTileSize;
11643     }
11644     else if (aFlag == "-nbtiles")
11645     {
11646       if (toPrint)
11647       {
11648         theDI << aParams.NbRayTracingTiles << " ";
11649         continue;
11650       }
11651       else if (++anArgIter >= theArgNb)
11652       {
11653         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11654         return 1;
11655       }
11656
11657       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11658       if (aNbTiles < -1)
11659       {
11660         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11661         return 1;
11662       }
11663       else if (aNbTiles > 0
11664             && (aNbTiles < 64
11665              || aNbTiles > 1024))
11666       {
11667         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11668       }
11669       aParams.NbRayTracingTiles = aNbTiles;
11670     }
11671     else if (aFlag == "-env")
11672     {
11673       if (toPrint)
11674       {
11675         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11676         continue;
11677       }
11678
11679       Standard_Boolean toEnable = Standard_True;
11680       if (++anArgIter < theArgNb
11681         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11682       {
11683         --anArgIter;
11684       }
11685       aParams.UseEnvironmentMapBackground = toEnable;
11686     }
11687     else if (aFlag == "-twoside")
11688     {
11689       if (toPrint)
11690       {
11691         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11692         continue;
11693       }
11694
11695       Standard_Boolean toEnable = Standard_True;
11696       if (++anArgIter < theArgNb
11697         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11698       {
11699         --anArgIter;
11700       }
11701       aParams.TwoSidedBsdfModels = toEnable;
11702     }
11703     else if (aFlag == "-shademodel"
11704           || aFlag == "-shadingmodel"
11705           || aFlag == "-shading")
11706     {
11707       if (toPrint)
11708       {
11709         switch (aView->ShadingModel())
11710         {
11711           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11712           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11713           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11714           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11715           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11716         }
11717         continue;
11718       }
11719
11720       if (++anArgIter >= theArgNb)
11721       {
11722         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11723       }
11724
11725       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11726       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11727        && aModel != Graphic3d_TOSM_DEFAULT)
11728       {
11729         aView->SetShadingModel (aModel);
11730       }
11731       else
11732       {
11733         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11734         return 1;
11735       }
11736     }
11737     else if (aFlag == "-resolution")
11738     {
11739       if (++anArgIter >= theArgNb)
11740       {
11741         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11742         return 1;
11743       }
11744
11745       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11746       if (aResolution.IsIntegerValue())
11747       {
11748         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11749       }
11750       else
11751       {
11752         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11753         return 1;
11754       }
11755     }
11756     else if (aFlag == "-rebuildglsl"
11757           || aFlag == "-rebuild")
11758     {
11759       if (toPrint)
11760       {
11761         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11762         continue;
11763       }
11764
11765       Standard_Boolean toEnable = Standard_True;
11766       if (++anArgIter < theArgNb
11767           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11768       {
11769         --anArgIter;
11770       }
11771       aParams.RebuildRayTracingShaders = toEnable;
11772     }
11773     else if (aFlag == "-focal")
11774     {
11775       if (++anArgIter >= theArgNb)
11776       {
11777         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11778         return 1;
11779       }
11780
11781       TCollection_AsciiString aParam (theArgVec[anArgIter]);
11782       if (aParam.IsRealValue())
11783       {
11784         float aFocalDist = static_cast<float> (aParam.RealValue());
11785         if (aFocalDist < 0)
11786         {
11787           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11788           return 1;
11789         }
11790         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
11791       }
11792       else
11793       {
11794         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11795         return 1;
11796       }
11797     }
11798     else if (aFlag == "-aperture")
11799     {
11800       if (++anArgIter >= theArgNb)
11801       {
11802         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11803         return 1;
11804       }
11805
11806       TCollection_AsciiString aParam(theArgVec[anArgIter]);
11807       if (aParam.IsRealValue())
11808       {
11809         float aApertureSize = static_cast<float> (aParam.RealValue());
11810         if (aApertureSize < 0)
11811         {
11812           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11813           return 1;
11814         }
11815         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
11816       }
11817       else
11818       {
11819         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11820         return 1;
11821       }
11822     }
11823     else if (aFlag == "-exposure")
11824     {
11825       if (++anArgIter >= theArgNb)
11826       {
11827         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11828         return 1;
11829       }
11830
11831       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
11832       if (anExposure.IsRealValue())
11833       {
11834         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11835       }
11836       else
11837       {
11838         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11839         return 1;
11840       }
11841     }
11842     else if (aFlag == "-whitepoint")
11843     {
11844       if (++anArgIter >= theArgNb)
11845       {
11846         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11847         return 1;
11848       }
11849
11850       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
11851       if (aWhitePoint.IsRealValue())
11852       {
11853         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11854       }
11855       else
11856       {
11857         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11858         return 1;
11859       }
11860     }
11861     else if (aFlag == "-tonemapping")
11862     {
11863       if (++anArgIter >= theArgNb)
11864       {
11865         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11866         return 1;
11867       }
11868
11869       TCollection_AsciiString aMode (theArgVec[anArgIter]);
11870       aMode.LowerCase();
11871
11872       if (aMode == "disabled")
11873       {
11874         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11875       }
11876       else if (aMode == "filmic")
11877       {
11878         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11879       }
11880       else
11881       {
11882         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11883         return 1;
11884       }
11885     }
11886     else if (aFlag == "-performancestats"
11887           || aFlag == "-performancecounters"
11888           || aFlag == "-perfstats"
11889           || aFlag == "-perfcounters"
11890           || aFlag == "-stats")
11891     {
11892       if (++anArgIter >= theArgNb)
11893       {
11894         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11895         return 1;
11896       }
11897
11898       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11899       aFlagsStr.LowerCase();
11900       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11901       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11902       {
11903         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11904         return 1;
11905       }
11906       aView->ChangeRenderingParams().CollectedStats = aFlags;
11907       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11908     }
11909     else if (aFlag == "-perfupdateinterval"
11910           || aFlag == "-statsupdateinterval")
11911     {
11912       if (++anArgIter >= theArgNb)
11913       {
11914         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11915         return 1;
11916       }
11917       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11918     }
11919     else if (aFlag == "-perfchart"
11920           || aFlag == "-statschart")
11921     {
11922       if (++anArgIter >= theArgNb)
11923       {
11924         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11925         return 1;
11926       }
11927       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
11928     }
11929     else if (aFlag == "-perfchartmax"
11930           || aFlag == "-statschartmax")
11931     {
11932       if (++anArgIter >= theArgNb)
11933       {
11934         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11935         return 1;
11936       }
11937       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11938     }
11939     else if (aFlag == "-frustumculling"
11940           || aFlag == "-culling")
11941     {
11942       if (toPrint)
11943       {
11944         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
11945                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
11946                                                                                                    "noUpdate") << " ";
11947         continue;
11948       }
11949
11950       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
11951       if (++anArgIter < theArgNb)
11952       {
11953         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
11954         aStateStr.LowerCase();
11955         bool toEnable = true;
11956         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
11957         {
11958           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
11959         }
11960         else if (aStateStr == "noupdate"
11961               || aStateStr == "freeze")
11962         {
11963           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
11964         }
11965         else
11966         {
11967           --anArgIter;
11968         }
11969       }
11970       aParams.FrustumCullingState = aState;
11971     }
11972     else
11973     {
11974       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
11975       return 1;
11976     }
11977   }
11978
11979   return 0;
11980 }
11981
11982 //=======================================================================
11983 //function : searchInfo
11984 //purpose  :
11985 //=======================================================================
11986 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
11987                                            const TCollection_AsciiString&              theKey)
11988 {
11989   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
11990   {
11991     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
11992     {
11993       return anIter.Value();
11994     }
11995   }
11996   return TCollection_AsciiString();
11997 }
11998
11999 //=======================================================================
12000 //function : VStatProfiler
12001 //purpose  :
12002 //=======================================================================
12003 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12004                                        Standard_Integer  theArgNb,
12005                                        const char**      theArgVec)
12006 {
12007   Handle(V3d_View) aView = ViewerTest::CurrentView();
12008   if (aView.IsNull())
12009   {
12010     std::cerr << "Error: no active viewer!\n";
12011     return 1;
12012   }
12013
12014   Standard_Boolean toRedraw = Standard_True;
12015   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12016   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12017   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12018   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12019   {
12020     Standard_CString        anArg (theArgVec[anArgIter]);
12021     TCollection_AsciiString aFlag (anArg);
12022     aFlag.LowerCase();
12023     if (aFlag == "-noredraw")
12024     {
12025       toRedraw = Standard_False;
12026     }
12027     else
12028     {
12029       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12030       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12031       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12032       else if (aFlag == "alllayers"
12033             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12034       else if (aFlag == "allstructs"
12035             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12036       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12037       else if (aFlag == "allarrays"
12038             || aFlag == "fillarrays"
12039             || aFlag == "linearrays"
12040             || aFlag == "pointarrays"
12041             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12042       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12043       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12044       else if (aFlag == "geommem"
12045             || aFlag == "texturemem"
12046             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12047       else if (aFlag == "elapsedframe"
12048             || aFlag == "cpuframeaverage"
12049             || aFlag == "cpupickingaverage"
12050             || aFlag == "cpucullingaverage"
12051             || aFlag == "cpudynaverage"
12052             || aFlag == "cpuframemax"
12053             || aFlag == "cpupickingmax"
12054             || aFlag == "cpucullingmax"
12055             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12056       else
12057       {
12058         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12059         continue;
12060       }
12061
12062       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12063     }
12064   }
12065
12066   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12067   {
12068     aView->ChangeRenderingParams().CollectedStats =
12069       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12070
12071     if (toRedraw)
12072     {
12073       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12074       aView->Redraw();
12075       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12076     }
12077
12078     TColStd_IndexedDataMapOfStringString aDict;
12079     aView->StatisticInformation (aDict);
12080
12081     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12082
12083     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12084     {
12085       Standard_CString        anArg(theArgVec[anArgIter]);
12086       TCollection_AsciiString aFlag(anArg);
12087       aFlag.LowerCase();
12088       if (aFlag == "fps")
12089       {
12090         theDI << searchInfo (aDict, "FPS") << " ";
12091       }
12092       else if (aFlag == "cpu")
12093       {
12094         theDI << searchInfo (aDict, "CPU FPS") << " ";
12095       }
12096       else if (aFlag == "alllayers")
12097       {
12098         theDI << searchInfo (aDict, "Layers") << " ";
12099       }
12100       else if (aFlag == "layers")
12101       {
12102         theDI << searchInfo (aDict, "Rendered layers") << " ";
12103       }
12104       else if (aFlag == "allstructs")
12105       {
12106         theDI << searchInfo (aDict, "Structs") << " ";
12107       }
12108       else if (aFlag == "structs")
12109       {
12110         theDI << searchInfo (aDict, "Rendered structs") << " ";
12111       }
12112       else if (aFlag == "groups")
12113       {
12114         theDI << searchInfo (aDict, "Rendered groups") << " ";
12115       }
12116       else if (aFlag == "allarrays")
12117       {
12118         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12119       }
12120       else if (aFlag == "fillarrays")
12121       {
12122         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12123       }
12124       else if (aFlag == "linearrays")
12125       {
12126         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12127       }
12128       else if (aFlag == "pointarrays")
12129       {
12130         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12131       }
12132       else if (aFlag == "textarrays")
12133       {
12134         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12135       }
12136       else if (aFlag == "triangles")
12137       {
12138         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12139       }
12140       else if (aFlag == "points")
12141       {
12142         theDI << searchInfo (aDict, "Rendered points") << " ";
12143       }
12144       else if (aFlag == "geommem")
12145       {
12146         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12147       }
12148       else if (aFlag == "texturemem")
12149       {
12150         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12151       }
12152       else if (aFlag == "framemem")
12153       {
12154         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12155       }
12156       else if (aFlag == "elapsedframe")
12157       {
12158         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12159       }
12160       else if (aFlag == "cpuframe_average")
12161       {
12162         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12163       }
12164       else if (aFlag == "cpupicking_average")
12165       {
12166         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12167       }
12168       else if (aFlag == "cpuculling_average")
12169       {
12170         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12171       }
12172       else if (aFlag == "cpudyn_average")
12173       {
12174         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12175       }
12176       else if (aFlag == "cpuframe_max")
12177       {
12178         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12179       }
12180       else if (aFlag == "cpupicking_max")
12181       {
12182         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12183       }
12184       else if (aFlag == "cpuculling_max")
12185       {
12186         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12187       }
12188       else if (aFlag == "cpudyn_max")
12189       {
12190         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12191       }
12192     }
12193   }
12194   else
12195   {
12196     if (toRedraw)
12197     {
12198       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12199       aView->Redraw();
12200       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12201     }
12202     theDI << "Statistic info:\n" << aView->StatisticInformation();
12203   }
12204   return 0;
12205 }
12206
12207 //=======================================================================
12208 //function : VXRotate
12209 //purpose  :
12210 //=======================================================================
12211 static Standard_Integer VXRotate (Draw_Interpretor& di,
12212                                    Standard_Integer argc,
12213                                    const char ** argv)
12214 {
12215   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12216   if (aContext.IsNull())
12217   {
12218     di << argv[0] << "ERROR : use 'vinit' command before \n";
12219     return 1;
12220   }
12221
12222   if (argc != 3)
12223   {
12224     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12225     return 1;
12226   }
12227
12228   TCollection_AsciiString aName (argv[1]);
12229   Standard_Real anAngle = Draw::Atof (argv[2]);
12230
12231   // find object
12232   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12233   Handle(AIS_InteractiveObject) anIObj;
12234   if (!aMap.Find2 (aName, anIObj))
12235   {
12236     di << "Use 'vdisplay' before\n";
12237     return 1;
12238   }
12239
12240   gp_Trsf aTransform;
12241   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12242   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12243
12244   aContext->SetLocation (anIObj, aTransform);
12245   aContext->UpdateCurrentViewer();
12246   return 0;
12247 }
12248
12249 //===============================================================================================
12250 //class   : ViewerTest_AISManipulator
12251 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12252 //===============================================================================================
12253 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12254
12255 class ViewerTest_AISManipulator : public AIS_Manipulator
12256 {
12257 public:
12258
12259   ViewerTest_AISManipulator() : AIS_Manipulator()
12260   {
12261     GetMapOfAISManipulators().Add (this);
12262   }
12263
12264   virtual ~ViewerTest_AISManipulator()
12265   {
12266     GetMapOfAISManipulators().Remove (this);
12267   }
12268
12269   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12270 };
12271
12272 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12273 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12274
12275 //===============================================================================================
12276 //function : VManipulator
12277 //purpose  :
12278 //===============================================================================================
12279 static int VManipulator (Draw_Interpretor& theDi,
12280                          Standard_Integer  theArgsNb,
12281                          const char**      theArgVec)
12282 {
12283   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12284   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12285   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12286   if (aCurrentView.IsNull()
12287    || aViewer.IsNull())
12288   {
12289     std::cerr << "No active viewer!\n";
12290     return 1;
12291   }
12292
12293   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12294   Standard_Integer anArgIter = 1;
12295   for (; anArgIter < theArgsNb; ++anArgIter)
12296   {
12297     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12298   }
12299
12300   ViewerTest_CmdParser aCmd;
12301   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12302   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12303   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12304   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12305   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12306   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12307   aCmd.AddOption ("detach",         "...       - detach manipulator");
12308
12309   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12310   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12311   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12312
12313   aCmd.AddOption ("move",   "... x y z - move object");
12314   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12315   aCmd.AddOption ("scale",  "... factor - scale object");
12316
12317   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12318   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12319   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12320   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12321   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12322   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12323   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12324   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12325   aCmd.AddOption ("size",              "... size - set size of manipulator");
12326   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12327
12328   aCmd.Parse (theArgsNb, theArgVec);
12329
12330   if (aCmd.HasOption ("help"))
12331   {
12332     theDi.PrintHelp (theArgVec[0]);
12333     return 0;
12334   }
12335
12336   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12337
12338   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12339
12340   if (aName.IsEmpty())
12341   {
12342     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12343     return 1;
12344   }
12345
12346   // ----------------------------------
12347   // detach existing manipulator object
12348   // ----------------------------------
12349
12350   if (aCmd.HasOption ("detach"))
12351   {
12352     if (!aMapAIS.IsBound2 (aName))
12353     {
12354       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12355       return 1;
12356     }
12357
12358     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12359     if (aManipulator.IsNull())
12360     {
12361       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12362       return 1;
12363     }
12364
12365     aManipulator->Detach();
12366     aMapAIS.UnBind2 (aName);
12367     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12368
12369     return 0;
12370   }
12371
12372   // -----------------------------------------------
12373   // find or create manipulator if it does not exist
12374   // -----------------------------------------------
12375
12376   Handle(AIS_Manipulator) aManipulator;
12377   if (!aMapAIS.IsBound2 (aName))
12378   {
12379     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12380
12381     aManipulator = new ViewerTest_AISManipulator();
12382     aManipulator->SetModeActivationOnDetection (true);
12383     aMapAIS.Bind (aManipulator, aName);
12384   }
12385   else
12386   {
12387     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12388     if (aManipulator.IsNull())
12389     {
12390       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12391       return 1;
12392     }
12393   }
12394
12395   // -----------------------------------------
12396   // change properties of manipulator instance
12397   // -----------------------------------------
12398
12399   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12400   {
12401     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12402   }
12403   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12404   {
12405     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12406   }
12407   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12408   {
12409     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12410   }
12411   if (aCmd.HasOption("followDragging", 1, Standard_True))
12412   {
12413     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12414   }
12415   if (aCmd.HasOption ("gap", 1, Standard_True))
12416   {
12417     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12418   }
12419   if (aCmd.HasOption ("part", 3, Standard_True))
12420   {
12421     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12422     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12423     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12424     if (aMode < 1 || aMode > 4)
12425     {
12426       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12427       return 1;
12428     }
12429
12430     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12431   }
12432   if (aCmd.HasOption("parts", 2, Standard_True))
12433   {
12434     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12435     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12436     if (aMode < 1 || aMode > 4)
12437     {
12438       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12439       return 1;
12440     }
12441
12442     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12443   }
12444   if (aCmd.HasOption ("pos", 3, Standard_True))
12445   {
12446     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12447     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12448     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12449
12450     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12451   }
12452   if (aCmd.HasOption ("size", 1, Standard_True))
12453   {
12454     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12455   }
12456   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12457   {
12458     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12459
12460     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12461     {
12462       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12463       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12464     }
12465   }
12466
12467   // ---------------------------------------------------
12468   // attach, detach or access manipulator from an object
12469   // ---------------------------------------------------
12470
12471   if (aCmd.HasOption ("attach"))
12472   {
12473     // Find an object and attach manipulator to it
12474     if (!aCmd.HasOption ("attach", 1, Standard_True))
12475     {
12476       return 1;
12477     }
12478
12479     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12480     Handle(AIS_InteractiveObject) anObject;
12481     if (!aMapAIS.Find2 (anObjName, anObject))
12482     {
12483       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12484       return 1;
12485     }
12486
12487     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12488     {
12489       if (anIt.Value()->IsAttached()
12490        && anIt.Value()->Object() == anObject)
12491       {
12492         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12493         return 1;
12494       }
12495     }
12496
12497     AIS_Manipulator::OptionsForAttach anOptions;
12498     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12499     {
12500       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12501     }
12502     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12503     {
12504       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12505     }
12506     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12507     {
12508       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12509     }
12510
12511     aManipulator->Attach (anObject, anOptions);
12512
12513     // Check view option
12514     if (aCmd.HasOption ("view"))
12515     {
12516       if (!aCmd.HasOption ("view", 1, Standard_True))
12517       {
12518         return 1;
12519       }
12520       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12521       Handle(V3d_View) aView;
12522       if (aViewString.IsEqual ("active"))
12523       {
12524         aView = ViewerTest::CurrentView();
12525       }
12526       else // Check view name
12527       {
12528         ViewerTest_Names aViewNames (aViewString);
12529         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12530         {
12531           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12532           return 1;
12533         }
12534         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12535         if (aView.IsNull())
12536         {
12537           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12538           return 1;
12539         }
12540       }
12541       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12542         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12543       {
12544         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12545       }
12546       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12547     }
12548   }
12549
12550   // --------------------------------------
12551   // apply transformation using manipulator
12552   // --------------------------------------
12553
12554   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12555   {
12556     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12557   }
12558   if (aCmd.HasOption ("transform", 2, Standard_True))
12559   {
12560     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12561   }
12562   if (aCmd.HasOption ("stopTransform"))
12563   {
12564     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12565
12566     aManipulator->StopTransform (toApply);
12567   }
12568
12569   gp_Trsf aT;
12570   if (aCmd.HasOption ("move", 3, Standard_True))
12571   {
12572     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12573   }
12574   if (aCmd.HasOption ("rotate", 7, Standard_True))
12575   {
12576     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12577   }
12578   if (aCmd.HasOption ("scale", 1))
12579   {
12580     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12581   }
12582
12583   if (aT.Form() != gp_Identity)
12584   {
12585     aManipulator->Transform (aT);
12586   }
12587
12588   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12589
12590   return 0;
12591 }
12592
12593 //===============================================================================================
12594 //function : VSelectionProperties
12595 //purpose  :
12596 //===============================================================================================
12597 static int VSelectionProperties (Draw_Interpretor& theDi,
12598                                  Standard_Integer  theArgsNb,
12599                                  const char**      theArgVec)
12600 {
12601   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12602   if (aCtx.IsNull())
12603   {
12604     std::cerr << "No active viewer!\n";
12605     return 1;
12606   }
12607
12608   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12609   {
12610     // handle obsolete alias
12611     bool toEnable = true;
12612     if (theArgsNb < 2)
12613     {
12614       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12615       return 0;
12616     }
12617     else if (theArgsNb != 2
12618          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12619     {
12620       std::cout << "Syntax error: wrong number of parameters.";
12621       return 1;
12622     }
12623     if (toEnable != aCtx->ToHilightSelected())
12624     {
12625       aCtx->ClearDetected();
12626       aCtx->SetToHilightSelected (toEnable);
12627     }
12628     return 0;
12629   }
12630
12631   Standard_Boolean toPrint  = theArgsNb == 1;
12632   Standard_Boolean toRedraw = Standard_False;
12633   Standard_Integer anArgIter = 1;
12634   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12635   if (anArgIter < theArgsNb)
12636   {
12637     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12638     anArgFirst.LowerCase();
12639     ++anArgIter;
12640     if (anArgFirst == "dynhighlight"
12641      || anArgFirst == "dynhilight"
12642      || anArgFirst == "dynamichighlight"
12643      || anArgFirst == "dynamichilight")
12644     {
12645       aType = Prs3d_TypeOfHighlight_Dynamic;
12646     }
12647     else if (anArgFirst == "localdynhighlight"
12648           || anArgFirst == "localdynhilight"
12649           || anArgFirst == "localdynamichighlight"
12650           || anArgFirst == "localdynamichilight")
12651     {
12652       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12653     }
12654     else if (anArgFirst == "selhighlight"
12655           || anArgFirst == "selhilight"
12656           || anArgFirst == "selectedhighlight"
12657           || anArgFirst == "selectedhilight")
12658     {
12659       aType = Prs3d_TypeOfHighlight_Selected;
12660     }
12661     else if (anArgFirst == "localselhighlight"
12662           || anArgFirst == "localselhilight"
12663           || anArgFirst == "localselectedhighlight"
12664           || anArgFirst == "localselectedhilight")
12665     {
12666       aType = Prs3d_TypeOfHighlight_LocalSelected;
12667     }
12668     else
12669     {
12670       --anArgIter;
12671     }
12672   }
12673   for (; anArgIter < theArgsNb; ++anArgIter)
12674   {
12675     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12676     anArg.LowerCase();
12677     if (anArg == "-help")
12678     {
12679       theDi.PrintHelp (theArgVec[0]);
12680       return 0;
12681     }
12682     else if (anArg == "-print")
12683     {
12684       toPrint = Standard_True;
12685     }
12686     else if (anArg == "-autoactivate")
12687     {
12688       Standard_Boolean toEnable = Standard_True;
12689       if (anArgIter + 1 < theArgsNb
12690        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12691       {
12692         ++anArgIter;
12693       }
12694       aCtx->SetAutoActivateSelection (toEnable);
12695     }
12696     else if (anArg == "-automatichighlight"
12697           || anArg == "-automatichilight"
12698           || anArg == "-autohighlight"
12699           || anArg == "-autohilight")
12700     {
12701       Standard_Boolean toEnable = Standard_True;
12702       if (anArgIter + 1 < theArgsNb
12703        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12704       {
12705         ++anArgIter;
12706       }
12707       aCtx->ClearSelected (false);
12708       aCtx->ClearDetected();
12709       aCtx->SetAutomaticHilight (toEnable);
12710       toRedraw = true;
12711     }
12712     else if (anArg == "-highlightselected"
12713           || anArg == "-hilightselected")
12714     {
12715       Standard_Boolean toEnable = Standard_True;
12716       if (anArgIter + 1 < theArgsNb
12717        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12718       {
12719         ++anArgIter;
12720       }
12721       aCtx->ClearDetected();
12722       aCtx->SetToHilightSelected (toEnable);
12723       toRedraw = true;
12724     }
12725     else if (anArg == "-pickstrategy"
12726           || anArg == "-pickingstrategy")
12727     {
12728       if (++anArgIter >= theArgsNb)
12729       {
12730         std::cout << "Syntax error: type of highlighting is undefined\n";
12731         return 1;
12732       }
12733
12734       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12735       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12736       aVal.LowerCase();
12737       if (aVal == "first"
12738        || aVal == "firstaccepted"
12739        || aVal == "firstacceptable")
12740       {
12741         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12742       }
12743       else if (aVal == "topmost"
12744             || aVal == "onlyTopmost")
12745       {
12746         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12747       }
12748       else
12749       {
12750         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12751         return 1;
12752       }
12753
12754       aCtx->SetPickingStrategy (aStrategy);
12755     }
12756     else if (anArg == "-pixtol"
12757           && anArgIter + 1 < theArgsNb)
12758     {
12759       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12760     }
12761     else if ((anArg == "-mode"
12762            || anArg == "-dispmode")
12763           && anArgIter + 1 < theArgsNb)
12764     {
12765       if (aType == Prs3d_TypeOfHighlight_None)
12766       {
12767         std::cout << "Syntax error: type of highlighting is undefined\n";
12768         return 1;
12769       }
12770
12771       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
12772       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12773       aStyle->SetDisplayMode (aDispMode);
12774       toRedraw = Standard_True;
12775     }
12776     else if (anArg == "-layer"
12777           && anArgIter + 1 < theArgsNb)
12778     {
12779       if (aType == Prs3d_TypeOfHighlight_None)
12780       {
12781         std::cout << "Syntax error: type of highlighting is undefined\n";
12782         return 1;
12783       }
12784
12785       ++anArgIter;
12786       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
12787       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
12788       {
12789         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
12790         return 1;
12791       }
12792
12793       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12794       aStyle->SetZLayer (aNewLayer);
12795       toRedraw = Standard_True;
12796     }
12797     else if (anArg == "-hicolor"
12798           || anArg == "-selcolor"
12799           || anArg == "-color")
12800     {
12801       if (anArg.StartsWith ("-hi"))
12802       {
12803         aType = Prs3d_TypeOfHighlight_Dynamic;
12804       }
12805       else if (anArg.StartsWith ("-sel"))
12806       {
12807         aType = Prs3d_TypeOfHighlight_Selected;
12808       }
12809       else if (aType == Prs3d_TypeOfHighlight_None)
12810       {
12811         std::cout << "Syntax error: type of highlighting is undefined\n";
12812         return 1;
12813       }
12814
12815       Quantity_Color aColor;
12816       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
12817                                                            theArgVec + anArgIter + 1,
12818                                                            aColor);
12819       if (aNbParsed == 0)
12820       {
12821         std::cout << "Syntax error: need more arguments.\n";
12822         return 1;
12823       }
12824       anArgIter += aNbParsed;
12825
12826       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12827       aStyle->SetColor (aColor);
12828       toRedraw = Standard_True;
12829     }
12830     else if ((anArg == "-transp"
12831            || anArg == "-transparency"
12832            || anArg == "-hitransp"
12833            || anArg == "-seltransp"
12834            || anArg == "-hitransplocal"
12835            || anArg == "-seltransplocal")
12836           && anArgIter + 1 < theArgsNb)
12837     {
12838       if (anArg.StartsWith ("-hi"))
12839       {
12840         aType = Prs3d_TypeOfHighlight_Dynamic;
12841       }
12842       else if (anArg.StartsWith ("-sel"))
12843       {
12844         aType = Prs3d_TypeOfHighlight_Selected;
12845       }
12846       else if (aType == Prs3d_TypeOfHighlight_None)
12847       {
12848         std::cout << "Syntax error: type of highlighting is undefined\n";
12849         return 1;
12850       }
12851
12852       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
12853       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12854       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
12855       toRedraw = Standard_True;
12856     }
12857     else if ((anArg == "-mat"
12858            || anArg == "-material")
12859           && anArgIter + 1 < theArgsNb)
12860     {
12861       if (aType == Prs3d_TypeOfHighlight_None)
12862       {
12863         std::cout << "Syntax error: type of highlighting is undefined\n";
12864         return 1;
12865       }
12866
12867       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12868       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
12869       if (aMatName != Graphic3d_NOM_DEFAULT)
12870       {
12871         ++anArgIter;
12872         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
12873         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
12874         Graphic3d_MaterialAspect aMat (aMatName);
12875         aMat.SetColor (aStyle->Color());
12876         aMat.SetTransparency (aStyle->Transparency());
12877         anAspect->SetFrontMaterial (aMat);
12878         anAspect->SetInteriorColor (aStyle->Color());
12879         aStyle->SetBasicFillAreaAspect (anAspect);
12880       }
12881       else
12882       {
12883         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
12884       }
12885       toRedraw = Standard_True;
12886     }
12887     else
12888     {
12889       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
12890     }
12891   }
12892
12893   if (toPrint)
12894   {
12895     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
12896     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
12897     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
12898     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
12899     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
12900     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
12901     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
12902     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
12903     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
12904     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
12905     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
12906     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
12907     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
12908     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
12909   }
12910
12911   if (aCtx->NbSelected() != 0 && toRedraw)
12912   {
12913     aCtx->HilightSelected (Standard_True);
12914   }
12915
12916   return 0;
12917 }
12918
12919 //===============================================================================================
12920 //function : VDumpSelectionImage
12921 //purpose  :
12922 //===============================================================================================
12923 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
12924                                 Standard_Integer  theArgsNb,
12925                                 const char**      theArgVec)
12926 {
12927   if (theArgsNb < 2)
12928   {
12929     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
12930     return 1;
12931   }
12932
12933   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
12934   if (aContext.IsNull())
12935   {
12936     std::cout << "Error: no active view.\n";
12937     return 1;
12938   }
12939
12940   TCollection_AsciiString aFile;
12941   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12942   Image_Format anImgFormat = Image_Format_BGR;
12943   Standard_Integer aPickedIndex = 1;
12944   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
12945   {
12946     TCollection_AsciiString aParam (theArgVec[anArgIter]);
12947     aParam.LowerCase();
12948     if (aParam == "-type")
12949     {
12950       if (++anArgIter >= theArgsNb)
12951       {
12952         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
12953         return 1;
12954       }
12955
12956       TCollection_AsciiString aValue (theArgVec[anArgIter]);
12957       aValue.LowerCase();
12958       if (aValue == "depth"
12959        || aValue == "normdepth"
12960        || aValue == "normalizeddepth")
12961       {
12962         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12963         anImgFormat = Image_Format_GrayF;
12964       }
12965       if (aValue == "depthinverted"
12966        || aValue == "normdepthinverted"
12967        || aValue == "normalizeddepthinverted"
12968        || aValue == "inverted")
12969       {
12970         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
12971         anImgFormat = Image_Format_GrayF;
12972       }
12973       else if (aValue == "unnormdepth"
12974             || aValue == "unnormalizeddepth")
12975       {
12976         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
12977         anImgFormat = Image_Format_GrayF;
12978       }
12979       else if (aValue == "objectcolor"
12980             || aValue == "object"
12981             || aValue == "color")
12982       {
12983         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
12984       }
12985       else if (aValue == "entitycolor"
12986             || aValue == "entity")
12987       {
12988         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
12989       }
12990       else if (aValue == "ownercolor"
12991             || aValue == "owner")
12992       {
12993         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
12994       }
12995       else if (aValue == "selectionmodecolor"
12996             || aValue == "selectionmode"
12997             || aValue == "selmodecolor"
12998             || aValue == "selmode")
12999       {
13000         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13001       }
13002     }
13003     else if (aParam == "-picked"
13004           || aParam == "-pickeddepth"
13005           || aParam == "-pickedindex")
13006     {
13007       if (++anArgIter >= theArgsNb)
13008       {
13009         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13010         return 1;
13011       }
13012
13013       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13014     }
13015     else if (aFile.IsEmpty())
13016     {
13017       aFile = theArgVec[anArgIter];
13018     }
13019     else
13020     {
13021       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13022       return 1;
13023     }
13024   }
13025   if (aFile.IsEmpty())
13026   {
13027     std::cout << "Syntax error: image file name is missing.\n";
13028     return 1;
13029   }
13030
13031   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13032   Standard_Integer aWidth = 0, aHeight = 0;
13033   aView->Window()->Size (aWidth, aHeight);
13034
13035   Image_AlienPixMap aPixMap;
13036   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13037   {
13038     std::cout << "Error: can't allocate image.\n";
13039     return 1;
13040   }
13041   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13042   {
13043     std::cout << "Error: can't generate selection image.\n";
13044     return 1;
13045   }
13046   if (!aPixMap.Save (aFile))
13047   {
13048     std::cout << "Error: can't save selection image.\n";
13049     return 0;
13050   }
13051   return 0;
13052 }
13053
13054 //=======================================================================
13055 //function : ViewerCommands
13056 //purpose  :
13057 //=======================================================================
13058
13059 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13060 {
13061
13062   const char *group = "ZeViewer";
13063   theCommands.Add("vinit",
13064           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13065     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13066   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13067     "\n\t\t:     [-display displayName]"
13068   #endif
13069     "\n\t\t: Creates new View window with specified name viewName."
13070     "\n\t\t: By default the new view is created in the viewer and in"
13071     "\n\t\t: graphic driver shared with active view."
13072     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13073     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13074     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13075 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13076     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13077     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13078 #endif
13079     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13080     "\n\t\t:  -width, -height width and heigth of window respectively."
13081     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13082     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13083     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13084     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13085     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13086     __FILE__,VInit,group);
13087   theCommands.Add("vclose" ,
13088     "[view_id [keep_context=0|1]]\n"
13089     "or vclose ALL - to remove all created views\n"
13090     " - removes view(viewer window) defined by its view_id.\n"
13091     " - keep_context: by default 0; if 1 and the last view is deleted"
13092     " the current context is not removed.",
13093     __FILE__,VClose,group);
13094   theCommands.Add("vactivate" ,
13095     "vactivate view_id [-noUpdate]"
13096     " - activates view(viewer window) defined by its view_id",
13097     __FILE__,VActivate,group);
13098   theCommands.Add("vviewlist",
13099     "vviewlist [format={tree, long}]"
13100     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13101     " - format: format of result output, if tree the output is a tree view;"
13102     "otherwise it's a list of full view names. By default format = tree",
13103     __FILE__,VViewList,group);
13104   theCommands.Add("vhelp" ,
13105     "vhelp            : display help on the viewer commands",
13106     __FILE__,VHelp,group);
13107   theCommands.Add("vviewproj",
13108           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13109     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13110     "\n\t\t: Setup view direction"
13111     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13112     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13113     "\n\t\t:             for example '+Z' will show front of the model,"
13114     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13115     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13116     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13117     __FILE__,VViewProj,group);
13118   theCommands.Add("vtop" ,
13119     "vtop or <T>      : Top view. Orientation +X+Y" ,
13120     __FILE__,VViewProj,group);
13121   theCommands.Add("vbottom" ,
13122     "vbottom          : Bottom view. Orientation +X-Y" ,
13123     __FILE__,VViewProj,group);
13124   theCommands.Add("vleft" ,
13125     "vleft            : Left view. Orientation -Y+Z" ,
13126     __FILE__,VViewProj,group);
13127   theCommands.Add("vright" ,
13128     "vright           : Right view. Orientation +Y+Z" ,
13129     __FILE__,VViewProj,group);
13130   theCommands.Add("vaxo" ,
13131     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13132     __FILE__,VViewProj,group);
13133   theCommands.Add("vfront" ,
13134     "vfront           : Front view. Orientation +X+Z" ,
13135     __FILE__,VViewProj,group);
13136   theCommands.Add("vback" ,
13137     "vback            : Back view. Orientation -X+Z" ,
13138     __FILE__,VViewProj,group);
13139   theCommands.Add("vpick" ,
13140     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13141     VPick,group);
13142   theCommands.Add("vfit",
13143     "vfit or <F> [-selected] [-noupdate]"
13144     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13145     __FILE__,VFit,group);
13146   theCommands.Add ("vfitarea",
13147     "vfitarea x1 y1 x2 y2"
13148     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13149     "\n\t\t: Fit view to show area located between two points"
13150     "\n\t\t: given in world 2D or 3D corrdinates.",
13151     __FILE__, VFitArea, group);
13152   theCommands.Add ("vzfit", "vzfit [scale]\n"
13153     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13154     "   \"scale\" - specifies factor to scale computed z range.\n",
13155     __FILE__, VZFit, group);
13156   theCommands.Add("vrepaint",
13157             "vrepaint [-immediate] [-continuous FPS]"
13158     "\n\t\t: force redraw of active View"
13159     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13160     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13161     "\n\t\t:                0 means no continuous rendering,"
13162     "\n\t\t:               -1 means non-stop redraws,"
13163     "\n\t\t:               >0 specifies target framerate,",
13164     __FILE__,VRepaint,group);
13165   theCommands.Add("vclear",
13166     "vclear          : vclear"
13167     "\n\t\t: remove all the object from the viewer",
13168     __FILE__,VClear,group);
13169   theCommands.Add (
13170     "vbackground",
13171     "Changes background or some background settings.\n"
13172     "\n"
13173     "Usage:\n"
13174     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13175     "  vbackground -imageMode FillType\n"
13176     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13177     "  vbackground -gradientMode FillMethod\n"
13178     "  vbackground -color Color\n"
13179     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13180     "  vbackground -default -color Color\n"
13181     "  vbackground -help\n"
13182     "\n"
13183     "Options:\n"
13184     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13185     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13186     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13187     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13188     "  -color        (-col):                               sets background color\n"
13189     "  -default      (-def):                               sets background default gradient or color\n"
13190     "  -help         (-h):                                 outputs short help message\n"
13191     "\n"
13192     "Arguments:\n"
13193     "  Color:      Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13194     "                                  or reals within the range [0.0, 1.0]\n"
13195     "              ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13196     "              #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13197     "  FillMethod: one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13198     "CORNER4\n"
13199     "  FillType:   one of CENTERED, TILED, STRETCH, NONE\n"
13200     "  ImageFile:  a name of the file with the image used as a background\n",
13201     __FILE__,
13202     vbackground,
13203     group);
13204   theCommands.Add ("vsetbg",
13205                    "Loads image as background."
13206                    "\n\t\t: vsetbg ImageFile [FillType]"
13207                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13208                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13209                    __FILE__,
13210                    vbackground,
13211                    group);
13212   theCommands.Add ("vsetbgmode",
13213                    "Changes background image fill type."
13214                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13215                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13216                    __FILE__,
13217                    vbackground,
13218                    group);
13219   theCommands.Add ("vsetgradientbg",
13220                    "Mounts gradient background."
13221                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13222                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13223                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13224                    __FILE__,
13225                    vbackground,
13226                    group);
13227   theCommands.Add ("vsetgrbgmode",
13228                    "Changes gradient background fill method."
13229                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13230                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13231                    __FILE__,
13232                    vbackground,
13233                    group);
13234   theCommands.Add ("vsetcolorbg",
13235                    "Sets background color."
13236                    "\n\t\t: vsetcolorbg [-color] Color."
13237                    "\n\t\t: Alias for 'vbackground -color Color'.",
13238                    __FILE__,
13239                    vbackground,
13240                    group);
13241   theCommands.Add ("vsetdefaultbg",
13242                    "Sets default viewer background fill color (flat/gradient)."
13243                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13244                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13245                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13246                    "\n\t\t: vsetdefaultbg [-color] Color"
13247                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13248                    __FILE__,
13249                    vbackground,
13250                    group);
13251   theCommands.Add("vscale",
13252     "vscale          : vscale X Y Z",
13253     __FILE__,VScale,group);
13254   theCommands.Add("vzbufftrihedron",
13255             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13256     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13257     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13258     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13259     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13260     "\n\t\t: Displays a trihedron",
13261     __FILE__,VZBuffTrihedron,group);
13262   theCommands.Add("vrotate",
13263     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13264     "\n                : Option -mouseStart starts rotation according to the mouse position"
13265     "\n                : Option -mouseMove continues rotation with angle computed"
13266     "\n                : from last and new mouse position."
13267     "\n                : vrotate AX AY AZ [X Y Z]",
13268     __FILE__,VRotate,group);
13269   theCommands.Add("vzoom",
13270     "vzoom           : vzoom coef",
13271     __FILE__,VZoom,group);
13272   theCommands.Add("vpan",
13273     "vpan            : vpan dx dy",
13274     __FILE__,VPan,group);
13275   theCommands.Add("vcolorscale",
13276     "vcolorscale name [-noupdate|-update] [-demo]"
13277     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13278     "\n\t\t:       [-font HeightFont=20]"
13279     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13280     "\n\t\t:       [-smoothTransition {on|off}=off]"
13281     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13282     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13283     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13284     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13285     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13286     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13287     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13288     "\n\t\t:       [-xy Left=0 Bottom=0]"
13289     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13290     "\n\t\t:  -colors   - set colors for all intervals"
13291     "\n\t\t:  -color    - set color for specific interval"
13292     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13293     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13294     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13295     "\n\t\t:              at center means the center value within current interval"
13296     "\n\t\t:  -labels   - set labels for all intervals"
13297     "\n\t\t:  -freeLabels - same as -labels but does not require"
13298     "\n\t\t:              matching the number of intervals"
13299     "\n\t\t:  -label    - set label for specific interval"
13300     "\n\t\t:  -title    - set title"
13301     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13302     "\n\t\t:  -smoothTransition - swap colorscale direction"
13303     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13304     __FILE__, VColorScale, group);
13305   theCommands.Add("vgraduatedtrihedron",
13306     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13307     "\t[-namefont Name] [-valuesfont Name]\n"
13308     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13309     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13310     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13311     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13312     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13313     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13314     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13315     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13316     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13317     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13318     " - Displays or erases graduated trihedron"
13319     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13320     " - namefont - font of axes names. Default: Arial\n"
13321     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13322     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13323     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13324     " - valuesfont - font of axes values. Default: Arial\n"
13325     " - xcolor, ycolor, zcolor - color of axis and values\n"
13326     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13327     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13328     __FILE__,VGraduatedTrihedron,group);
13329   theCommands.Add("vtile" ,
13330             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13331     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13332     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13333     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13334     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13335     "\n\t\t:  -upperLeft tile offset as upper left corner",
13336     __FILE__, VTile, group);
13337   theCommands.Add("vzlayer",
13338               "vzlayer [layerId]"
13339       "\n\t\t:         [-add|-delete|-get|-settings]"
13340       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13341       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13342       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv}]"
13343       "\n\t\t: ZLayer list management:"
13344       "\n\t\t:   -add      add new z layer to viewer and print its id"
13345       "\n\t\t:   -delete   delete z layer"
13346       "\n\t\t:   -get      print sequence of z layers"
13347       "\n\t\t:   -settings print status of z layer settings"
13348       "\n\t\t:   -disable  disables given setting"
13349       "\n\t\t:   -enable   enables  given setting",
13350     __FILE__,VZLayer,group);
13351   theCommands.Add("vlayerline",
13352     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
13353     __FILE__,VLayerLine,group);
13354   theCommands.Add("vgrid",
13355               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
13356       "\n\t\t:       [-step X Y] [-size DX DY]"
13357       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
13358     __FILE__, VGrid, group);
13359   theCommands.Add ("vpriviledgedplane",
13360     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
13361     "\n\t\t:   Ox, Oy, Oz - plane origin"
13362     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
13363     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
13364     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
13365     __FILE__, VPriviledgedPlane, group);
13366   theCommands.Add ("vconvert",
13367     "vconvert v [Mode={window|view}]"
13368     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
13369     "\n\t\t: vconvert x y z [Mode={window|grid}]"
13370     "\n\t\t:   window - convert to window coordinates, pixels"
13371     "\n\t\t:   view   - convert to view projection plane"
13372     "\n\t\t:   grid   - convert to model coordinates, given on grid"
13373     "\n\t\t:   ray    - convert projection ray to model coordiantes"
13374     "\n\t\t: - vconvert v window : convert view to window;"
13375     "\n\t\t: - vconvert v view   : convert window to view;"
13376     "\n\t\t: - vconvert x y window : convert view to window;"
13377     "\n\t\t: - vconvert x y view : convert window to view;"
13378     "\n\t\t: - vconvert x y : convert window to model;"
13379     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
13380     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
13381     "\n\t\t: - vconvert x y z window : convert model to window;"
13382     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
13383     "\n\t\t: Converts the given coordinates to window/view/model space.",
13384     __FILE__, VConvert, group);
13385   theCommands.Add ("vfps",
13386     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
13387     __FILE__, VFps, group);
13388   theCommands.Add ("vgldebug",
13389             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
13390     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
13391     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
13392     "\n\t\t: Debug context can be requested only on Windows"
13393     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
13394     "\n\t\t:  -sync     - request synchronized debug GL context"
13395     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
13396     "\n\t\t:              which are suppressed by default,"
13397     "\n\t\t:  -glslCode - log GLSL program source code,"
13398     "\n\t\t:              which are suppressed by default,"
13399     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
13400     "\n\t\t:              which are suppressed by default",
13401     __FILE__, VGlDebug, group);
13402   theCommands.Add ("vvbo",
13403     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
13404     __FILE__, VVbo, group);
13405   theCommands.Add ("vstereo",
13406             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
13407     "\n\t\t:         [-anaglyph Filter]"
13408     "\n\t\t: Control stereo output mode. Available modes for -mode:"
13409     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
13410     "\n\t\t:                     requires driver support."
13411     "\n\t\t:                     Should be called BEFORE vinit!"
13412     "\n\t\t:  anaglyph         - Anaglyph glasses"
13413     "\n\t\t:  rowInterlaced    - row-interlaced display"
13414     "\n\t\t:  columnInterlaced - column-interlaced display"
13415     "\n\t\t:  chessBoard       - chess-board output"
13416     "\n\t\t:  sideBySide       - horizontal pair"
13417     "\n\t\t:  overUnder        - vertical   pair"
13418     "\n\t\t: Available Anaglyph filters for -anaglyph:"
13419     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
13420     "\n\t\t:  greenMagentaSimple",
13421     __FILE__, VStereo, group);
13422   theCommands.Add ("vcaps",
13423             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
13424     "\n\t\t:       [-compatibleProfile {0|1}]"
13425     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
13426     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
13427     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
13428     "\n\t\t: Modify particular graphic driver options:"
13429     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
13430     "\n\t\t:             built-in GLSL programs"
13431     "\n\t\t:            (requires compatible profile)"
13432     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
13433     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
13434     "\n\t\t:             arrays to GPU memory)"
13435     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
13436     "\n\t\t:  vsync    - switch VSync on or off"
13437     "\n\t\t:  winBuffer - allow using window buffer for rendering"
13438     "\n\t\t: Context creation options:"
13439     "\n\t\t:  softMode          - software OpenGL implementation"
13440     "\n\t\t:  compatibleProfile - backward-compatible profile"
13441     "\n\t\t:  quadbuffer        - QuadBuffer"
13442     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13443     "\n\t\t: rendering paths producing the same visual result when"
13444     "\n\t\t: possible."
13445     "\n\t\t: Command is intended for testing old hardware compatibility.",
13446     __FILE__, VCaps, group);
13447   theCommands.Add ("vmemgpu",
13448     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13449     " with f option returns free memory in bytes",
13450     __FILE__, VMemGpu, group);
13451   theCommands.Add ("vreadpixel",
13452     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13453     " : Read pixel value for active view",
13454     __FILE__, VReadPixel, group);
13455   theCommands.Add("diffimage",
13456             "diffimage imageFile1 imageFile2 [diffImageFile]"
13457     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13458     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13459     "\n\t\t: Compare two images by content and generate difference image."
13460     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13461     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13462     __FILE__, VDiffImage, group);
13463   theCommands.Add ("vselect",
13464     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13465     "- emulates different types of selection:\n"
13466     "- 1) single click selection\n"
13467     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13468     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13469     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13470     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13471     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13472     " (partial inclusion - overlap - is not allowed by default)\n"
13473     "- 5) any of these selections with shift button pressed",
13474     __FILE__, VSelect, group);
13475   theCommands.Add ("vmoveto",
13476     "vmoveto [x y] [-reset]"
13477     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13478     "\n\t\t:   -reset resets current highlighting",
13479     __FILE__, VMoveTo, group);
13480   theCommands.Add ("vviewparams",
13481               "vviewparams [-args] [-scale [s]]"
13482       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13483       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13484       "\n\t\t: Manage current view parameters or prints all"
13485       "\n\t\t: current values when called without argument."
13486       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13487       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13488       "\n\t\t:   -at   [x y z] prints or sets center of look"
13489       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13490       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13491       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13492       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13493       "\n\t\t:                 or changes the size of its maximum dimension"
13494       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13495     __FILE__, VViewParams, group);
13496
13497   theCommands.Add("v2dmode",
13498     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
13499     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
13500     "\n\t\t:   mode   - switches On/Off rotation mode"
13501     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
13502     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
13503     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
13504     "\n\t\t: View camera position might be changed only by commands.",
13505     __FILE__, V2DMode, group);
13506
13507   theCommands.Add("vanimation", "Alias for vanim",
13508     __FILE__, VAnimation, group);
13509
13510   theCommands.Add("vanim",
13511             "List existing animations:"
13512     "\n\t\t:  vanim"
13513     "\n\t\t: Animation playback:"
13514     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
13515     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
13516     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
13517     "\n\t\t:   -freeLook skip camera animations"
13518     "\n\t\t:   -lockLoop disable any interactions"
13519     "\n\t\t:"
13520     "\n\t\t: Animation definition:"
13521     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
13522     "\n\t\t:        [start TimeSec] [duration TimeSec]"
13523     "\n\t\t:"
13524     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
13525     "\n\t\t: specifies nested animations."
13526     "\n\t\t: There is no syntax to explicitly add new animation,"
13527     "\n\t\t: and all non-existing animations within the name will be"
13528     "\n\t\t: implicitly created on first use (including parents)."
13529     "\n\t\t:"
13530     "\n\t\t: Each animation might define the SINGLE action (see below),"
13531     "\n\t\t: like camera transition, object transformation or custom callback."
13532     "\n\t\t: Child animations can be used for defining concurrent actions."
13533     "\n\t\t:"
13534     "\n\t\t: Camera animation:"
13535     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
13536     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
13537     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
13538     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
13539     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
13540     "\n\t\t:   -atX    camera Center positions pair"
13541     "\n\t\t:   -upX    camera Up directions pair"
13542     "\n\t\t:   -scaleX camera Scale factors pair"
13543     "\n\t\t: Object animation:"
13544     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
13545     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
13546     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
13547     "\n\t\t:   -locX   object Location points pair (translation)"
13548     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
13549     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
13550     "\n\t\t: Custom callback:"
13551     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
13552     "\n\t\t:   %Pts        overall animation presentation timestamp"
13553     "\n\t\t:   %LocalPts   local animation timestamp"
13554     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
13555     "\n\t\t:"
13556     "\n\t\t: Video recording:"
13557     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
13558     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
13559     "\n\t\t:             [-crf Value] [-preset Preset]"
13560     "\n\t\t:   -fps     video framerate"
13561     "\n\t\t:   -format  file format, container (matroska, etc.)"
13562     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
13563     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
13564     "\n\t\t:   -crf     constant rate factor (specific to codec)"
13565     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
13566     __FILE__, VAnimation, group);
13567
13568   theCommands.Add("vchangeselected",
13569     "vchangeselected shape"
13570     "- adds to shape to selection or remove one from it",
13571                 __FILE__, VChangeSelected, group);
13572   theCommands.Add ("vnbselected",
13573     "vnbselected"
13574     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
13575   theCommands.Add ("vcamera",
13576               "vcamera [PrsName] [-ortho] [-projtype]"
13577       "\n\t\t:         [-persp]"
13578       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
13579       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
13580       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
13581       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
13582       "\n\t\t: Manages camera parameters."
13583       "\n\t\t: Displays frustum when presntation name PrsName is specified."
13584       "\n\t\t: Prints current value when option called without argument."
13585       "\n\t\t: Orthographic camera:"
13586       "\n\t\t:   -ortho      activate orthographic projection"
13587       "\n\t\t: Perspective camera:"
13588       "\n\t\t:   -persp      activate perspective  projection (mono)"
13589       "\n\t\t:   -fovy       field of view in y axis, in degrees"
13590       "\n\t\t:   -distance   distance of eye from camera center"
13591       "\n\t\t: Stereoscopic camera:"
13592       "\n\t\t:   -stereo     perspective  projection (stereo)"
13593       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
13594       "\n\t\t:   -rightEye   perspective  projection (right eye)"
13595       "\n\t\t:   -iod        intraocular distance value"
13596       "\n\t\t:   -iodType    distance type, absolute or relative"
13597       "\n\t\t:   -zfocus     stereographic focus value"
13598       "\n\t\t:   -zfocusType focus type, absolute or relative",
13599     __FILE__, VCamera, group);
13600   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
13601     "- vautozfit [on={1|0}] [scale]\n"
13602     "    Prints or changes parameters of automatic z-fit mode:\n"
13603     "   \"on\" - turns automatic z-fit on or off\n"
13604     "   \"scale\" - specifies factor to scale computed z range.\n",
13605     __FILE__, VAutoZFit, group);
13606   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
13607     "   vzrange                - without parameters shows current values\n"
13608     "   vzrange [znear] [zfar] - applies provided values to view",
13609     __FILE__,VZRange, group);
13610   theCommands.Add ("vpurgedisplay",
13611     "vpurgedisplay"
13612     "- removes structures which don't belong to objects displayed in neutral point",
13613     __FILE__, VPurgeDisplay, group);
13614   theCommands.Add("vsetviewsize",
13615     "vsetviewsize size",
13616     __FILE__,VSetViewSize,group);
13617   theCommands.Add("vmoveview",
13618     "vmoveview Dx Dy Dz [Start = 1|0]",
13619     __FILE__,VMoveView,group);
13620   theCommands.Add("vtranslateview",
13621     "vtranslateview Dx Dy Dz [Start = 1|0)]",
13622     __FILE__,VTranslateView,group);
13623   theCommands.Add("vturnview",
13624     "vturnview Ax Ay Az [Start = 1|0]",
13625     __FILE__,VTurnView,group);
13626   theCommands.Add("vtextureenv",
13627     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
13628     "or user-defined file and optionally applying texture mapping parameters\n"
13629     "                  Usage:\n"
13630     "                  vtextureenv off - disables environment mapping\n"
13631     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
13632     "                              std_texture = (0..7)\n"
13633     "                              rep         = {clamp|repeat}\n"
13634     "                              mod         = {decal|modulate}\n"
13635     "                              flt         = {nearest|bilinear|trilinear}\n"
13636     "                              ss, st      - scale factors for s and t texture coordinates\n"
13637     "                              ts, tt      - translation for s and t texture coordinates\n"
13638     "                              rot         - texture rotation angle in degrees",
13639     __FILE__, VTextureEnv, group);
13640   theCommands.Add("vhlr",
13641             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
13642       "\n\t\t: Hidden Line Removal algorithm."
13643       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
13644       "\n\t\t:   -algoType   type of HLR algorithm.\n",
13645     __FILE__,VHLR,group);
13646   theCommands.Add("vhlrtype",
13647               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
13648       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
13649       "\n\t\t:   'algo' - exact HLR algorithm is applied"
13650       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
13651       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
13652     __FILE__,VHLRType,group);
13653   theCommands.Add("vclipplane",
13654               "vclipplane planeName [{0|1}]"
13655       "\n\t\t:   [-equation1 A B C D]"
13656       "\n\t\t:   [-equation2 A B C D]"
13657       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
13658       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
13659       "\n\t\t:   [-maxPlanes]"
13660       "\n\t\t:   [-capping {0|1}]"
13661       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
13662       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
13663       "\n\t\t:       [-texRotate Angle]"
13664       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
13665       "\n\t\t:       [-useObjShader {0|1}]"
13666       "\n\t\t: Clipping planes management:"
13667       "\n\t\t:   -maxPlanes   print plane limit for view"
13668       "\n\t\t:   -delete      delete plane with given name"
13669       "\n\t\t:   {off|on|0|1} turn clipping on/off"
13670       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
13671       "\n\t\t:                applied to active View when list is omitted"
13672       "\n\t\t:   -equation A B C D change plane equation"
13673       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
13674       "\n\t\t: Capping options:"
13675       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
13676       "\n\t\t:   -color R G B          set capping color"
13677       "\n\t\t:   -transparency Value   set capping transparency 0..1"
13678       "\n\t\t:   -texName Texture      set capping texture"
13679       "\n\t\t:   -texScale SX SY       set capping tex scale"
13680       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
13681       "\n\t\t:   -texRotate Angle      set capping tex rotation"
13682       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
13683       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
13684       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
13685       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
13686       __FILE__, VClipPlane, group);
13687   theCommands.Add("vdefaults",
13688                "vdefaults [-absDefl value]"
13689        "\n\t\t:           [-devCoeff value]"
13690        "\n\t\t:           [-angDefl value]"
13691        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
13692     , __FILE__, VDefaults, group);
13693   theCommands.Add("vlight",
13694     "tool to manage light sources, without arguments shows list of lights."
13695     "\n    Main commands: "
13696     "\n      '-clear' to clear lights"
13697     "\n      '-{def}aults' to load deafault lights"
13698     "\n      '-add' <type> to add any light source"
13699     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
13700     "\n      'change' <lightId> to edit light source with specified lightId"
13701     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
13702     "\n        -layer Id"
13703     "\n        -{pos}ition X Y Z"
13704     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
13705     "\n        -color colorName"
13706     "\n        -{head}light 0|1"
13707     "\n        -{sm}oothness value"
13708     "\n        -{int}ensity value"
13709     "\n        -{constAtten}uation value"
13710     "\n        -{linearAtten}uation value"
13711     "\n        -angle angleDeg"
13712     "\n        -{spotexp}onent value"
13713     "\n        -local|-global"
13714     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
13715     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
13716     __FILE__, VLight, group);
13717   theCommands.Add("vraytrace",
13718             "vraytrace [0|1]"
13719     "\n\t\t: Turns on/off ray-tracing renderer."
13720     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
13721     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
13722     __FILE__, VRenderParams, group);
13723   theCommands.Add("vrenderparams",
13724     "\n    Manages rendering parameters: "
13725     "\n      '-raster'                   Disables GPU ray-tracing"
13726     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
13727     "\n      '-lineFeather  > 0'         Sets line feather factor"
13728     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
13729     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
13730     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
13731     "\n      '-rendScale    value        Rendering resolution scale factor"
13732     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
13733     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
13734     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
13735     "\n      '-reflections  on|off'      Enables/disables specular reflections"
13736     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
13737     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
13738     "\n      '-gi           on|off'      Enables/disables global illumination effects"
13739     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
13740     "\n      '-env          on|off'      Enables/disables environment map background"
13741     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
13742     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
13743     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
13744     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
13745     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
13746     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
13747     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
13748     "\n      '-shadingModel model'       Controls shading model from enumeration"
13749     "\n                                  color, flat, gouraud, phong"
13750     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
13751     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
13752     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
13753     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
13754     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
13755     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
13756     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
13757     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
13758     "\n                                  Show/hide performance counters (flags can be combined)"
13759     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
13760     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
13761     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
13762     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
13763     "\n                                        set state to check structures culled previously."
13764     "\n    Unlike vcaps, these parameters dramatically change visual properties."
13765     "\n    Command is intended to control presentation quality depending on"
13766     "\n    hardware capabilities and performance.",
13767     __FILE__, VRenderParams, group);
13768   theCommands.Add("vstatprofiler",
13769     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
13770     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
13771     "\n                |triagles|points|geomMem|textureMem|frameMem"
13772     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
13773     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
13774     "\n                [-noredraw]"
13775     "\n\t\t: Prints rendering statistics."
13776     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
13777     "\n\t\t:   else - print all performance counters set previously."
13778     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
13779     __FILE__, VStatProfiler, group);
13780   theCommands.Add ("vplace",
13781             "vplace dx dy"
13782     "\n\t\t: Places the point (in pixels) at the center of the window",
13783     __FILE__, VPlace, group);
13784   theCommands.Add("vxrotate",
13785     "vxrotate",
13786     __FILE__,VXRotate,group);
13787
13788     theCommands.Add("vmanipulator",
13789       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
13790       "\n    tool to create and manage AIS manipulators."
13791       "\n    Options: "
13792       "\n      '-attach AISObject'                 attach manipulator to AISObject"
13793       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
13794       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
13795       "\n      '-enableModes    {0|1}'             enable modes when attaching"
13796       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
13797       "\n                                          by default it is displayed in all views of the current viewer"
13798       "\n      '-detach'                           detach manipulator"
13799       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
13800       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
13801       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
13802       "\n      '-move x y z'                     - move attached object"
13803       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
13804       "\n      '-scale factor'                   - scale attached object"
13805       "\n      '-autoActivate      {0|1}'        - set activation on detection"
13806       "\n      '-followTranslation {0|1}'        - set following translation transform"
13807       "\n      '-followRotation    {0|1}'        - set following rotation transform"
13808       "\n      '-followDragging    {0|1}'        - set following dragging transform"
13809       "\n      '-gap value'                      - set gap between sub-parts"
13810       "\n      '-part axis mode    {0|1}'        - set visual part"
13811       "\n      '-parts axis mode   {0|1}'        - set visual part"
13812       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
13813       "\n      '-size value'                     - set size of manipulator"
13814       "\n      '-zoomable {0|1}'                 - set zoom persistence",
13815     __FILE__, VManipulator, group);
13816
13817   theCommands.Add("vselprops",
13818     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
13819     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
13820     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
13821     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
13822     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
13823     "\n    -pickStrategy {first|topmost} : defines picking strategy"
13824     "\n                            'first'   to pick first acceptable (default)"
13825     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
13826     "\n    -pixTol    value        : sets up pixel tolerance"
13827     "\n    -dispMode  dispMode     : sets display mode for highlighting"
13828     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
13829     "\n    -color     {name|r g b} : sets highlight color"
13830     "\n    -transp    value        : sets transparency coefficient for highlight"
13831     "\n    -material  material     : sets highlight material"
13832     "\n    -print                  : prints current state of all mentioned parameters",
13833     __FILE__, VSelectionProperties, group);
13834   theCommands.Add ("vhighlightselected",
13835                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
13836                    __FILE__, VSelectionProperties, group);
13837
13838   theCommands.Add ("vseldump",
13839                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
13840                    "\n\t\t: Generate an image based on detection results:"
13841                    "\n\t\t:   depth       normalized depth values"
13842                    "\n\t\t:   unnormDepth unnormalized depth values"
13843                    "\n\t\t:   object      color of detected object"
13844                    "\n\t\t:   owner       color of detected owner"
13845                    "\n\t\t:   selMode     color of selection mode"
13846                    "\n\t\t:   entity      color of etected entity",
13847                    __FILE__, VDumpSelectionImage, group);
13848 }
13849