0030668: Visualization - revise adding ZLayer API
[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   Graphic3d_ZLayerId anOtherLayerId = Graphic3d_ZLayerId_UNKNOWN;
5326   for (; anArgIter < theArgNb; ++anArgIter)
5327   {
5328     // perform operation
5329     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5330     anArg.LowerCase();
5331     if (anUpdateTool.parseRedrawMode (anArg))
5332     {
5333       //
5334     }
5335     else if (anArg == "-add"
5336           || anArg == "add")
5337     {
5338       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5339       if (!aViewer->AddZLayer (aLayerId))
5340       {
5341         std::cout << "Error: can not add a new z layer!\n";
5342         return 0;
5343       }
5344
5345       theDI << aLayerId;
5346     }
5347     else if (anArg == "-insertbefore"
5348           && anArgIter + 1 < theArgNb
5349           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5350     {
5351       ++anArgIter;
5352       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5353       if (!aViewer->InsertLayerBefore (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5354       {
5355         std::cout << "Error: can not add a new z layer!\n";
5356         return 0;
5357       }
5358
5359       theDI << aLayerId;
5360     }
5361     else if (anArg == "-insertafter"
5362           && anArgIter + 1 < theArgNb
5363           && ViewerTest::ParseZLayer (theArgVec[anArgIter + 1], anOtherLayerId))
5364     {
5365       ++anArgIter;
5366       aLayerId = Graphic3d_ZLayerId_UNKNOWN;
5367       if (!aViewer->InsertLayerAfter (aLayerId, Graphic3d_ZLayerSettings(), anOtherLayerId))
5368       {
5369         std::cout << "Error: can not add a new z layer!\n";
5370         return 0;
5371       }
5372
5373       theDI << aLayerId;
5374     }
5375     else if (anArg == "-del"
5376           || anArg == "-delete"
5377           || anArg == "del")
5378     {
5379       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5380       {
5381         if (++anArgIter >= theArgNb)
5382         {
5383           std::cout << "Syntax error: id of z layer to remove is missing\n";
5384           return 1;
5385         }
5386
5387         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5388       }
5389
5390       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN
5391        || aLayerId == Graphic3d_ZLayerId_Default
5392        || aLayerId == Graphic3d_ZLayerId_Top
5393        || aLayerId == Graphic3d_ZLayerId_Topmost
5394        || aLayerId == Graphic3d_ZLayerId_TopOSD
5395        || aLayerId == Graphic3d_ZLayerId_BotOSD)
5396       {
5397         std::cout << "Syntax error: standard Z layer can not be removed\n";
5398         return 1;
5399       }
5400
5401       // move all object displayed in removing layer to default layer
5402       for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anObjIter (GetMapOfAIS());
5403            anObjIter.More(); anObjIter.Next())
5404       {
5405         const Handle(AIS_InteractiveObject)& aPrs = anObjIter.Key1();
5406         if (aPrs.IsNull()
5407          || aPrs->ZLayer() != aLayerId)
5408         {
5409           continue;
5410         }
5411         aPrs->SetZLayer (Graphic3d_ZLayerId_Default);
5412       }
5413
5414       if (!aViewer->RemoveZLayer (aLayerId))
5415       {
5416         std::cout << "Z layer can not be removed!\n";
5417       }
5418       else
5419       {
5420         theDI << aLayerId << " ";
5421       }
5422     }
5423     else if (anArg == "-get"
5424           || anArg == "get")
5425     {
5426       TColStd_SequenceOfInteger aLayers;
5427       aViewer->GetAllZLayers (aLayers);
5428       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
5429       {
5430         theDI << aLayeriter.Value() << " ";
5431       }
5432
5433       theDI << "\n";
5434     }
5435     else if (anArg == "-name")
5436     {
5437       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5438       {
5439         std::cout << "Syntax error: id of Z layer is missing\n";
5440         return 1;
5441       }
5442
5443       if (++anArgIter >= theArgNb)
5444       {
5445         std::cout << "Syntax error: name is missing\n";
5446         return 1;
5447       }
5448
5449       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5450       aSettings.SetName (theArgVec[anArgIter]);
5451       aViewer->SetZLayerSettings (aLayerId, aSettings);
5452     }
5453     else if (anArg == "-origin")
5454     {
5455       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5456       {
5457         std::cout << "Syntax error: id of Z layer is missing\n";
5458         return 1;
5459       }
5460
5461       if (anArgIter + 2 >= theArgNb)
5462       {
5463         std::cout << "Syntax error: origin coordinates are missing\n";
5464         return 1;
5465       }
5466
5467       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5468       gp_XYZ anOrigin;
5469       anOrigin.SetX (Draw::Atof (theArgVec[anArgIter + 1]));
5470       anOrigin.SetY (Draw::Atof (theArgVec[anArgIter + 2]));
5471       anOrigin.SetZ (0.0);
5472       if (anArgIter + 3 < theArgNb)
5473       {
5474         anOrigin.SetZ (Draw::Atof (theArgVec[anArgIter + 3]));
5475         anArgIter += 3;
5476       }
5477       else
5478       {
5479         anArgIter += 2;
5480       }
5481       aSettings.SetOrigin (anOrigin);
5482       aViewer->SetZLayerSettings (aLayerId, aSettings);
5483     }
5484     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5485           && anArgIter + 1 < theArgNb
5486           && (anArg == "-cullingdistance"
5487            || anArg == "-cullingdist"
5488            || anArg == "-culldistance"
5489            || anArg == "-culldist"
5490            || anArg == "-distcull"
5491            || anArg == "-distculling"
5492            || anArg == "-distanceculling"))
5493     {
5494       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5495       const Standard_Real aDist = Draw::Atof (theArgVec[++anArgIter]);
5496       aSettings.SetCullingDistance (aDist);
5497       aViewer->SetZLayerSettings (aLayerId, aSettings);
5498     }
5499     else if (aLayerId != Graphic3d_ZLayerId_UNKNOWN
5500           && anArgIter + 1 < theArgNb
5501           && (anArg == "-cullingsize"
5502            || anArg == "-cullsize"
5503            || anArg == "-sizecull"
5504            || anArg == "-sizeculling"))
5505     {
5506       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5507       const Standard_Real aSize = Draw::Atof (theArgVec[++anArgIter]);
5508       aSettings.SetCullingSize (aSize);
5509       aViewer->SetZLayerSettings (aLayerId, aSettings);
5510     }
5511     else if (anArg == "-settings"
5512           || anArg == "settings")
5513     {
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       printZLayerInfo (theDI, aSettings);
5527     }
5528     else if (anArg == "-enable"
5529           || anArg == "enable"
5530           || anArg == "-disable"
5531           || anArg == "disable")
5532     {
5533       const Standard_Boolean toEnable = anArg == "-enable"
5534                                      || anArg == "enable";
5535       if (++anArgIter >= theArgNb)
5536       {
5537         std::cout << "Syntax error: option name is missing\n";
5538         return 1;
5539       }
5540
5541       TCollection_AsciiString aSubOp (theArgVec[anArgIter]);
5542       aSubOp.LowerCase();
5543       if (aLayerId == Graphic3d_ZLayerId_UNKNOWN)
5544       {
5545         if (++anArgIter >= theArgNb)
5546         {
5547           std::cout << "Syntax error: id of Z layer is missing\n";
5548           return 1;
5549         }
5550
5551         aLayerId = Draw::Atoi (theArgVec[anArgIter]);
5552       }
5553
5554       Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayerId);
5555       if (aSubOp == "depthtest"
5556        || aSubOp == "test")
5557       {
5558         aSettings.SetEnableDepthTest (toEnable);
5559       }
5560       else if (aSubOp == "depthwrite"
5561             || aSubOp == "write")
5562       {
5563         aSettings.SetEnableDepthWrite (toEnable);
5564       }
5565       else if (aSubOp == "depthclear"
5566             || aSubOp == "clear")
5567       {
5568         aSettings.SetClearDepth (toEnable);
5569       }
5570       else if (aSubOp == "depthoffset"
5571             || aSubOp == "offset")
5572       {
5573         Graphic3d_PolygonOffset aParams;
5574         aParams.Mode = toEnable ? Aspect_POM_Fill : Aspect_POM_None;
5575         if (toEnable)
5576         {
5577           if (anArgIter + 2 >= theArgNb)
5578           {
5579             std::cout << "Syntax error: factor and units values for depth offset are missing\n";
5580             return 1;
5581           }
5582
5583           aParams.Factor = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5584           aParams.Units  = static_cast<Standard_ShortReal> (Draw::Atof (theArgVec[++anArgIter]));
5585         }
5586         aSettings.SetPolygonOffset (aParams);
5587       }
5588       else if (aSubOp == "positiveoffset"
5589             || aSubOp == "poffset")
5590       {
5591         if (toEnable)
5592         {
5593           aSettings.SetDepthOffsetPositive();
5594         }
5595         else
5596         {
5597           aSettings.SetPolygonOffset (Graphic3d_PolygonOffset());
5598         }
5599       }
5600       else if (aSubOp == "negativeoffset"
5601             || aSubOp == "noffset")
5602       {
5603         if (toEnable)
5604         {
5605           aSettings.SetDepthOffsetNegative();
5606         }
5607         else
5608         {
5609           aSettings.SetPolygonOffset(Graphic3d_PolygonOffset());
5610         }
5611       }
5612       else if (aSubOp == "textureenv")
5613       {
5614         aSettings.SetEnvironmentTexture (toEnable);
5615       }
5616       else if (aSubOp == "raytracing")
5617       {
5618         aSettings.SetRaytracable (toEnable);
5619       }
5620
5621       aViewer->SetZLayerSettings (aLayerId, aSettings);
5622     }
5623     else
5624     {
5625       std::cout << "Syntax error: unknown option " << theArgVec[anArgIter] << "\n";
5626       return 1;
5627     }
5628   }
5629
5630   return 0;
5631 }
5632
5633 // The interactive presentation of 2d layer item
5634 // for "vlayerline" command it provides a presentation of
5635 // line with user-defined linewidth, linetype and transparency.
5636 class V3d_LineItem : public AIS_InteractiveObject
5637 {
5638 public:
5639   // CASCADE RTTI
5640   DEFINE_STANDARD_RTTI_INLINE(V3d_LineItem,AIS_InteractiveObject)
5641
5642   // constructor
5643   Standard_EXPORT V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5644                                Standard_Real X2, Standard_Real Y2,
5645                                Aspect_TypeOfLine theType = Aspect_TOL_SOLID,
5646                                Standard_Real theWidth    = 0.5,
5647                                Standard_Real theTransp   = 1.0);
5648
5649   private:
5650
5651   void Compute (const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
5652                 const Handle(Prs3d_Presentation)& thePresentation,
5653                 const Standard_Integer theMode) Standard_OVERRIDE;
5654
5655   void ComputeSelection (const Handle(SelectMgr_Selection)& /*aSelection*/,
5656                          const Standard_Integer /*aMode*/) Standard_OVERRIDE
5657   {}
5658
5659 private:
5660
5661   Standard_Real       myX1, myY1, myX2, myY2;
5662   Aspect_TypeOfLine   myType;
5663   Standard_Real       myWidth;
5664 };
5665
5666 // default constructor for line item
5667 V3d_LineItem::V3d_LineItem(Standard_Real X1, Standard_Real Y1,
5668                            Standard_Real X2, Standard_Real Y2,
5669                            Aspect_TypeOfLine theType,
5670                            Standard_Real theWidth,
5671                            Standard_Real theTransp) :
5672   myX1(X1), myY1(Y1), myX2(X2), myY2(Y2),
5673   myType(theType), myWidth(theWidth)
5674 {
5675   SetTransparency (1-theTransp);
5676 }
5677
5678 // render line
5679 void V3d_LineItem::Compute (const Handle(PrsMgr_PresentationManager3d)& /*thePresentationManager*/,
5680                             const Handle(Prs3d_Presentation)& thePresentation,
5681                             const Standard_Integer /*theMode*/)
5682 {
5683   thePresentation->Clear();
5684   Quantity_Color aColor (1.0, 0, 0, Quantity_TOC_RGB);
5685   Standard_Integer aWidth, aHeight;
5686   ViewerTest::CurrentView()->Window()->Size (aWidth, aHeight);
5687   Handle (Graphic3d_Group) aGroup = Prs3d_Root::CurrentGroup (thePresentation);
5688   Handle(Graphic3d_ArrayOfPolylines) aPrim = new Graphic3d_ArrayOfPolylines(5);
5689   aPrim->AddVertex(myX1, aHeight-myY1, 0.);
5690   aPrim->AddVertex(myX2, aHeight-myY2, 0.);
5691   Handle(Prs3d_LineAspect) anAspect = new Prs3d_LineAspect (aColor, (Aspect_TypeOfLine)myType, myWidth);
5692   aGroup->SetPrimitivesAspect (anAspect->Aspect());
5693   aGroup->AddPrimitiveArray (aPrim);
5694 }
5695
5696 //=============================================================================
5697 //function : VLayerLine
5698 //purpose  : Draws line in the v3d view layer with given attributes: linetype,
5699 //         : linewidth, transparency coefficient
5700 //============================================================================
5701 static int VLayerLine(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
5702 {
5703   // get the active view
5704   Handle(V3d_View) aView = ViewerTest::CurrentView();
5705   if (aView.IsNull())
5706   {
5707     di << "Call vinit before!\n";
5708     return 1;
5709   }
5710   else if (argc < 5)
5711   {
5712     di << "Use: " << argv[0];
5713     di << " x1 y1 x2 y2 [linewidth = 0.5] [linetype = 0] [transparency = 1]\n";
5714     di << " linetype : { 0 | 1 | 2 | 3 } \n";
5715     di << "              0 - solid  \n";
5716     di << "              1 - dashed \n";
5717     di << "              2 - dot    \n";
5718     di << "              3 - dashdot\n";
5719     di << " transparency : { 0.0 - 1.0 } \n";
5720     di << "                  0.0 - transparent\n";
5721     di << "                  1.0 - visible    \n";
5722     return 1;
5723   }
5724
5725   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
5726   // get the input params
5727   Standard_Real X1 = Draw::Atof(argv[1]);
5728   Standard_Real Y1 = Draw::Atof(argv[2]);
5729   Standard_Real X2 = Draw::Atof(argv[3]);
5730   Standard_Real Y2 = Draw::Atof(argv[4]);
5731
5732   Standard_Real aWidth = 0.5;
5733   Standard_Real aTransparency = 1.0;
5734
5735   // has width
5736   if (argc > 5)
5737     aWidth = Draw::Atof(argv[5]);
5738
5739   // select appropriate line type
5740   Aspect_TypeOfLine aLineType = Aspect_TOL_SOLID;
5741   if (argc > 6
5742   && !ViewerTest::ParseLineType (argv[6], aLineType))
5743   {
5744     std::cout << "Syntax error: unknown line type '" << argv[6] << "'\n";
5745     return 1;
5746   }
5747
5748   // has transparency
5749   if (argc > 7)
5750   {
5751     aTransparency = Draw::Atof(argv[7]);
5752     if (aTransparency < 0 || aTransparency > 1.0)
5753       aTransparency = 1.0;
5754   }
5755
5756   static Handle (V3d_LineItem) aLine;
5757   if (!aLine.IsNull())
5758   {
5759     aContext->Erase (aLine, Standard_False);
5760   }
5761   aLine = new V3d_LineItem (X1, Y1, X2, Y2,
5762                             aLineType, aWidth,
5763                             aTransparency);
5764
5765   aContext->SetTransformPersistence (aLine, new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER));
5766   aLine->SetZLayer (Graphic3d_ZLayerId_TopOSD);
5767   aLine->SetToUpdate();
5768   aContext->Display (aLine, Standard_True);
5769
5770   return 0;
5771 }
5772
5773
5774 //==============================================================================
5775 //function : VGrid
5776 //purpose  :
5777 //==============================================================================
5778
5779 static int VGrid (Draw_Interpretor& /*theDI*/,
5780                   Standard_Integer  theArgNb,
5781                   const char**      theArgVec)
5782 {
5783   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
5784   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
5785   if (aView.IsNull() || aViewer.IsNull())
5786   {
5787     std::cerr << "Error: no active view\n";
5788     return 1;
5789   }
5790
5791   Aspect_GridType     aType = aViewer->GridType();
5792   Aspect_GridDrawMode aMode = aViewer->GridDrawMode();
5793   Graphic3d_Vec2d aNewOriginXY, aNewStepXY, aNewSizeXY;
5794   Standard_Real aNewRotAngle = 0.0, aNewZOffset = 0.0;
5795   bool hasOrigin = false, hasStep = false, hasRotAngle = false, hasSize = false, hasZOffset = false;
5796   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
5797   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
5798   {
5799     TCollection_AsciiString anArg (theArgVec[anArgIter]);
5800     anArg.LowerCase();
5801     if (anUpdateTool.parseRedrawMode (theArgVec[anArgIter]))
5802     {
5803       continue;
5804     }
5805     else if (anArgIter + 1 < theArgNb
5806           && anArg == "-type")
5807     {
5808       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5809       anArgNext.LowerCase();
5810       if (anArgNext == "r"
5811        || anArgNext == "rect"
5812        || anArgNext == "rectangular")
5813       {
5814         aType = Aspect_GT_Rectangular;
5815       }
5816       else if (anArgNext == "c"
5817             || anArgNext == "circ"
5818             || anArgNext == "circular")
5819       {
5820         aType = Aspect_GT_Circular;
5821       }
5822       else
5823       {
5824         std::cout << "Syntax error at '" << anArgNext << "'\n";
5825         return 1;
5826       }
5827     }
5828     else if (anArgIter + 1 < theArgNb
5829           && anArg == "-mode")
5830     {
5831       TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
5832       anArgNext.LowerCase();
5833       if (anArgNext == "l"
5834        || anArgNext == "line"
5835        || anArgNext == "lines")
5836       {
5837         aMode = Aspect_GDM_Lines;
5838       }
5839       else if (anArgNext == "p"
5840             || anArgNext == "point"
5841             || anArgNext == "points")
5842       {
5843         aMode = Aspect_GDM_Points;
5844       }
5845       else
5846       {
5847         std::cout << "Syntax error at '" << anArgNext << "'\n";
5848         return 1;
5849       }
5850     }
5851     else if (anArgIter + 2 < theArgNb
5852           && (anArg == "-origin"
5853            || anArg == "-orig"))
5854     {
5855       hasOrigin = true;
5856       aNewOriginXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5857                               Draw::Atof (theArgVec[anArgIter + 2]));
5858       anArgIter += 2;
5859     }
5860     else if (anArgIter + 2 < theArgNb
5861           && anArg == "-step")
5862     {
5863       hasStep = true;
5864       aNewStepXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5865                             Draw::Atof (theArgVec[anArgIter + 2]));
5866       if (aNewStepXY.x() <= 0.0
5867        || aNewStepXY.y() <= 0.0)
5868       {
5869         std::cout << "Syntax error: wrong step '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5870         return 1;
5871       }
5872       anArgIter += 2;
5873     }
5874     else if (anArgIter + 1 < theArgNb
5875           && (anArg == "-angle"
5876            || anArg == "-rotangle"
5877            || anArg == "-rotationangle"))
5878     {
5879       hasRotAngle = true;
5880       aNewRotAngle = Draw::Atof (theArgVec[++anArgIter]);
5881     }
5882     else if (anArgIter + 1 < theArgNb
5883           && (anArg == "-zoffset"
5884            || anArg == "-dz"))
5885     {
5886       hasZOffset = true;
5887       aNewZOffset = Draw::Atof (theArgVec[++anArgIter]);
5888     }
5889     else if (anArgIter + 1 < theArgNb
5890           && anArg == "-radius")
5891     {
5892       hasSize = true;
5893       ++anArgIter;
5894       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter]), 0.0);
5895       if (aNewStepXY.x() <= 0.0)
5896       {
5897         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter] << "'\n";
5898         return 1;
5899       }
5900     }
5901     else if (anArgIter + 2 < theArgNb
5902           && anArg == "-size")
5903     {
5904       hasSize = true;
5905       aNewSizeXY.SetValues (Draw::Atof (theArgVec[anArgIter + 1]),
5906                             Draw::Atof (theArgVec[anArgIter + 2]));
5907       if (aNewStepXY.x() <= 0.0
5908        || aNewStepXY.y() <= 0.0)
5909       {
5910         std::cout << "Syntax error: wrong size '" << theArgVec[anArgIter + 1] << " " << theArgVec[anArgIter + 2] << "'\n";
5911         return 1;
5912       }
5913       anArgIter += 2;
5914     }
5915     else if (anArg == "r"
5916           || anArg == "rect"
5917           || anArg == "rectangular")
5918     {
5919       aType = Aspect_GT_Rectangular;
5920     }
5921     else if (anArg == "c"
5922           || anArg == "circ"
5923           || anArg == "circular")
5924     {
5925       aType = Aspect_GT_Circular;
5926     }
5927     else if (anArg == "l"
5928           || anArg == "line"
5929           || anArg == "lines")
5930     {
5931       aMode = Aspect_GDM_Lines;
5932     }
5933     else if (anArg == "p"
5934           || anArg == "point"
5935           || anArg == "points")
5936     {
5937       aMode = Aspect_GDM_Points;
5938     }
5939     else if (anArgIter + 1 >= theArgNb
5940           && anArg == "off")
5941     {
5942       aViewer->DeactivateGrid();
5943       return 0;
5944     }
5945     else
5946     {
5947       std::cout << "Syntax error at '" << anArg << "'\n";
5948       return 1;
5949     }
5950   }
5951
5952   if (aType == Aspect_GT_Rectangular)
5953   {
5954     Graphic3d_Vec2d anOrigXY, aStepXY;
5955     Standard_Real aRotAngle = 0.0;
5956     aViewer->RectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5957     if (hasOrigin)
5958     {
5959       anOrigXY = aNewOriginXY;
5960     }
5961     if (hasStep)
5962     {
5963       aStepXY = aNewStepXY;
5964     }
5965     if (hasRotAngle)
5966     {
5967       aRotAngle = aNewRotAngle;
5968     }
5969     aViewer->SetRectangularGridValues (anOrigXY.x(), anOrigXY.y(), aStepXY.x(), aStepXY.y(), aRotAngle);
5970     if (hasSize || hasZOffset)
5971     {
5972       Graphic3d_Vec3d aSize;
5973       aViewer->RectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5974       if (hasSize)
5975       {
5976         aSize.x() = aNewSizeXY.x();
5977         aSize.y() = aNewSizeXY.y();
5978       }
5979       if (hasZOffset)
5980       {
5981         aSize.z() = aNewZOffset;
5982       }
5983       aViewer->SetRectangularGridGraphicValues (aSize.x(), aSize.y(), aSize.z());
5984     }
5985   }
5986   else if (aType == Aspect_GT_Circular)
5987   {
5988     Graphic3d_Vec2d anOrigXY;
5989     Standard_Real aRadiusStep;
5990     Standard_Integer aDivisionNumber;
5991     Standard_Real aRotAngle = 0.0;
5992     aViewer->CircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
5993     if (hasOrigin)
5994     {
5995       anOrigXY = aNewOriginXY;
5996     }
5997     if (hasStep)
5998     {
5999       aRadiusStep     = aNewStepXY[0];
6000       aDivisionNumber = (int )aNewStepXY[1];
6001       if (aDivisionNumber < 1)
6002       {
6003         std::cout << "Syntax error: invalid division number '" << aNewStepXY[1] << "'\n";
6004         return 1;
6005       }
6006     }
6007     if (hasRotAngle)
6008     {
6009       aRotAngle = aNewRotAngle;
6010     }
6011
6012     aViewer->SetCircularGridValues (anOrigXY.x(), anOrigXY.y(), aRadiusStep, aDivisionNumber, aRotAngle);
6013     if (hasSize || hasZOffset)
6014     {
6015       Standard_Real aRadius = 0.0, aZOffset = 0.0;
6016       aViewer->CircularGridGraphicValues (aRadius, aZOffset);
6017       if (hasSize)
6018       {
6019         aRadius = aNewSizeXY.x();
6020         if (aNewSizeXY.y() != 0.0)
6021         {
6022           std::cout << "Syntax error: circular size should be specified as radius\n";
6023           return 1;
6024         }
6025       }
6026       if (hasZOffset)
6027       {
6028         aZOffset = aNewZOffset;
6029       }
6030       aViewer->SetCircularGridGraphicValues (aRadius, aZOffset);
6031     }
6032   }
6033   aViewer->ActivateGrid (aType, aMode);
6034   return 0;
6035 }
6036
6037 //==============================================================================
6038 //function : VPriviledgedPlane
6039 //purpose  :
6040 //==============================================================================
6041
6042 static int VPriviledgedPlane (Draw_Interpretor& theDI,
6043                               Standard_Integer  theArgNb,
6044                               const char**      theArgVec)
6045 {
6046   if (theArgNb != 1 && theArgNb != 7 && theArgNb != 10)
6047   {
6048     std::cerr << "Error: wrong number of arguments! See usage:\n";
6049     theDI.PrintHelp (theArgVec[0]);
6050     return 1;
6051   }
6052
6053   // get the active viewer
6054   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
6055   if (aViewer.IsNull())
6056   {
6057     std::cerr << "Error: no active viewer. Please call vinit.\n";
6058     return 1;
6059   }
6060
6061   if (theArgNb == 1)
6062   {
6063     gp_Ax3 aPriviledgedPlane = aViewer->PrivilegedPlane();
6064     const gp_Pnt& anOrig = aPriviledgedPlane.Location();
6065     const gp_Dir& aNorm = aPriviledgedPlane.Direction();
6066     const gp_Dir& aXDir = aPriviledgedPlane.XDirection();
6067     theDI << "Origin: " << anOrig.X() << " " << anOrig.Y() << " " << anOrig.Z() << " "
6068           << "Normal: " << aNorm.X() << " " << aNorm.Y() << " " << aNorm.Z() << " "
6069           << "X-dir: "  << aXDir.X() << " " << aXDir.Y() << " " << aXDir.Z() << "\n";
6070     return 0;
6071   }
6072
6073   Standard_Integer anArgIdx = 1;
6074   Standard_Real anOrigX = Draw::Atof (theArgVec[anArgIdx++]);
6075   Standard_Real anOrigY = Draw::Atof (theArgVec[anArgIdx++]);
6076   Standard_Real anOrigZ = Draw::Atof (theArgVec[anArgIdx++]);
6077   Standard_Real aNormX  = Draw::Atof (theArgVec[anArgIdx++]);
6078   Standard_Real aNormY  = Draw::Atof (theArgVec[anArgIdx++]);
6079   Standard_Real aNormZ  = Draw::Atof (theArgVec[anArgIdx++]);
6080
6081   gp_Ax3 aPriviledgedPlane;
6082   gp_Pnt anOrig (anOrigX, anOrigY, anOrigZ);
6083   gp_Dir aNorm (aNormX, aNormY, aNormZ);
6084   if (theArgNb > 7)
6085   {
6086     Standard_Real aXDirX = Draw::Atof (theArgVec[anArgIdx++]);
6087     Standard_Real aXDirY = Draw::Atof (theArgVec[anArgIdx++]);
6088     Standard_Real aXDirZ = Draw::Atof (theArgVec[anArgIdx++]);
6089     gp_Dir aXDir (aXDirX, aXDirY, aXDirZ);
6090     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm, aXDir);
6091   }
6092   else
6093   {
6094     aPriviledgedPlane = gp_Ax3 (anOrig, aNorm);
6095   }
6096
6097   aViewer->SetPrivilegedPlane (aPriviledgedPlane);
6098
6099   return 0;
6100 }
6101
6102 //==============================================================================
6103 //function : VConvert
6104 //purpose  :
6105 //==============================================================================
6106
6107 static int VConvert (Draw_Interpretor& theDI,
6108                      Standard_Integer  theArgNb,
6109                      const char**      theArgVec)
6110 {
6111   // get the active view
6112   Handle(V3d_View) aView = ViewerTest::CurrentView();
6113   if (aView.IsNull())
6114   {
6115     std::cerr << "Error: no active view. Please call vinit.\n";
6116     return 1;
6117   }
6118
6119   enum { Model, Ray, View, Window, Grid } aMode = Model;
6120
6121   // access coordinate arguments
6122   TColStd_SequenceOfReal aCoord;
6123   Standard_Integer anArgIdx = 1;
6124   for (; anArgIdx < 4 && anArgIdx < theArgNb; ++anArgIdx)
6125   {
6126     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6127     if (!anArg.IsRealValue())
6128     {
6129       break;
6130     }
6131     aCoord.Append (anArg.RealValue());
6132   }
6133
6134   // non-numeric argument too early
6135   if (aCoord.IsEmpty())
6136   {
6137     std::cerr << "Error: wrong number of arguments! See usage:\n";
6138     theDI.PrintHelp (theArgVec[0]);
6139     return 1;
6140   }
6141
6142   // collect all other arguments and options
6143   for (; anArgIdx < theArgNb; ++anArgIdx)
6144   {
6145     TCollection_AsciiString anArg (theArgVec[anArgIdx]);
6146     anArg.LowerCase();
6147     if      (anArg == "window") aMode = Window;
6148     else if (anArg == "view")   aMode = View;
6149     else if (anArg == "grid")   aMode = Grid;
6150     else if (anArg == "ray")    aMode = Ray;
6151     else
6152     {
6153       std::cerr << "Error: wrong argument " << anArg << "! See usage:\n";
6154       theDI.PrintHelp (theArgVec[0]);
6155       return 1;
6156     }
6157   }
6158
6159   // complete input checks
6160   if ((aCoord.Length() == 1 && theArgNb > 3) ||
6161       (aCoord.Length() == 2 && theArgNb > 4) ||
6162       (aCoord.Length() == 3 && theArgNb > 5))
6163   {
6164     std::cerr << "Error: wrong number of arguments! See usage:\n";
6165     theDI.PrintHelp (theArgVec[0]);
6166     return 1;
6167   }
6168
6169   Standard_Real aXYZ[6] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
6170   Standard_Integer aXYp[2] = {0, 0};
6171
6172   // convert one-dimensional coordinate
6173   if (aCoord.Length() == 1)
6174   {
6175     switch (aMode)
6176     {
6177       case View   : theDI << "View Vv: "   << aView->Convert ((Standard_Integer)aCoord (1)); return 0;
6178       case Window : theDI << "Window Vp: " << aView->Convert (aCoord (1)); return 0;
6179       default:
6180         std::cerr << "Error: wrong arguments! See usage:\n";
6181         theDI.PrintHelp (theArgVec[0]);
6182         return 1;
6183     }
6184   }
6185
6186   // convert 2D coordinates from projection or view reference space
6187   if (aCoord.Length() == 2)
6188   {
6189     switch (aMode)
6190     {
6191       case Model :
6192         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6193         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6194         return 0;
6195
6196       case View :
6197         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1]);
6198         theDI << "View Xv,Yv: " << aXYZ[0] << " " << aXYZ[1] << "\n";
6199         return 0;
6200
6201       case Window :
6202         aView->Convert (aCoord (1), aCoord (2), aXYp[0], aXYp[1]);
6203         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6204         return 0;
6205
6206       case Grid :
6207         aView->Convert ((Standard_Integer) aCoord (1), (Standard_Integer) aCoord (2), aXYZ[0], aXYZ[1], aXYZ[2]);
6208         aView->ConvertToGrid (aXYZ[0], aXYZ[1], aXYZ[2], aXYZ[3], aXYZ[4], aXYZ[5]);
6209         theDI << "Model X,Y,Z: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6210         return 0;
6211
6212       case Ray :
6213         aView->ConvertWithProj ((Standard_Integer) aCoord (1),
6214                                 (Standard_Integer) aCoord (2),
6215                                 aXYZ[0], aXYZ[1], aXYZ[2],
6216                                 aXYZ[3], aXYZ[4], aXYZ[5]);
6217         theDI << "Model DX,DY,DZ: " << aXYZ[3] << " " << aXYZ[4] << " " << aXYZ[5] << "\n";
6218         return 0;
6219
6220       default:
6221         std::cerr << "Error: wrong arguments! See usage:\n";
6222         theDI.PrintHelp (theArgVec[0]);
6223         return 1;
6224     }
6225   }
6226
6227   // convert 3D coordinates from view reference space
6228   else if (aCoord.Length() == 3)
6229   {
6230     switch (aMode)
6231     {
6232       case Window :
6233         aView->Convert (aCoord (1), aCoord (2), aCoord (3), aXYp[0], aXYp[1]);
6234         theDI << "Window Xp,Yp: " << aXYp[0] << " " << aXYp[1] << "\n";
6235         return 0;
6236
6237       case Grid :
6238         aView->ConvertToGrid (aCoord (1), aCoord (2), aCoord (3), aXYZ[0], aXYZ[1], aXYZ[2]);
6239         theDI << "Model X,Y,Z: " << aXYZ[0] << " " << aXYZ[1] << " " << aXYZ[2] << "\n";
6240         return 0;
6241
6242       default:
6243         std::cerr << "Error: wrong arguments! See usage:\n";
6244         theDI.PrintHelp (theArgVec[0]);
6245         return 1;
6246     }
6247   }
6248
6249   return 0;
6250 }
6251
6252 //==============================================================================
6253 //function : VFps
6254 //purpose  :
6255 //==============================================================================
6256
6257 static int VFps (Draw_Interpretor& theDI,
6258                  Standard_Integer  theArgNb,
6259                  const char**      theArgVec)
6260 {
6261   // get the active view
6262   Handle(V3d_View) aView = ViewerTest::CurrentView();
6263   if (aView.IsNull())
6264   {
6265     std::cerr << "No active view. Please call vinit.\n";
6266     return 1;
6267   }
6268
6269   Standard_Integer aFramesNb = -1;
6270   Standard_Real aDuration = -1.0;
6271   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6272   {
6273     TCollection_AsciiString anArg (theArgVec[anArgIter]);
6274     anArg.LowerCase();
6275     if (aDuration < 0.0
6276      && anArgIter + 1 < theArgNb
6277      && (anArg == "-duration"
6278       || anArg == "-dur"
6279       || anArg == "-time"))
6280     {
6281       aDuration = Draw::Atof (theArgVec[++anArgIter]);
6282     }
6283     else if (aFramesNb < 0
6284           && anArg.IsIntegerValue())
6285     {
6286       aFramesNb = anArg.IntegerValue();
6287       if (aFramesNb <= 0)
6288       {
6289         std::cerr << "Syntax error at '" << anArg << "'\n";
6290         return 1;
6291       }
6292     }
6293     else
6294     {
6295       std::cerr << "Syntax error at '" << anArg << "'\n";
6296       return 1;
6297     }
6298   }
6299   if (aFramesNb < 0 && aDuration < 0.0)
6300   {
6301     aFramesNb = 100;
6302   }
6303
6304   // the time is meaningless for first call
6305   // due to async OpenGl rendering
6306   aView->Redraw();
6307
6308   // redraw view in loop to estimate average values
6309   OSD_Timer aTimer;
6310   aTimer.Start();
6311   Standard_Integer aFrameIter = 1;
6312   for (;; ++aFrameIter)
6313   {
6314     aView->Redraw();
6315     if ((aFramesNb > 0
6316       && aFrameIter >= aFramesNb)
6317      || (aDuration > 0.0
6318       && aTimer.ElapsedTime() >= aDuration))
6319     {
6320       break;
6321     }
6322   }
6323   aTimer.Stop();
6324   Standard_Real aCpu;
6325   const Standard_Real aTime = aTimer.ElapsedTime();
6326   aTimer.OSD_Chronometer::Show (aCpu);
6327
6328   const Standard_Real aFpsAver = Standard_Real(aFrameIter) / aTime;
6329   const Standard_Real aCpuAver = aCpu / Standard_Real(aFrameIter);
6330
6331   // return statistics
6332   theDI << "FPS: " << aFpsAver << "\n"
6333         << "CPU: " << (1000.0 * aCpuAver) << " msec\n";
6334
6335   // compute additional statistics in ray-tracing mode
6336   const Graphic3d_RenderingParams& aParams = aView->RenderingParams();
6337   if (aParams.Method == Graphic3d_RM_RAYTRACING)
6338   {
6339     Graphic3d_Vec2i aWinSize (0, 0);
6340     aView->Window()->Size (aWinSize.x(), aWinSize.y());
6341
6342     // 1 shadow ray and 1 secondary ray pew each bounce
6343     const Standard_Real aMRays = aWinSize.x() * aWinSize.y() * aFpsAver * aParams.RaytracingDepth * 2 / 1.0e6f;
6344     theDI << "MRays/sec (upper bound): " << aMRays << "\n";
6345   }
6346
6347   return 0;
6348 }
6349
6350 //! Auxiliary function for parsing glsl dump level argument.
6351 static Standard_Boolean parseGlslSourceFlag (Standard_CString               theArg,
6352                                              OpenGl_ShaderProgramDumpLevel& theGlslDumpLevel)
6353 {
6354   TCollection_AsciiString aTypeStr (theArg);
6355   aTypeStr.LowerCase();
6356   if (aTypeStr == "off"
6357    || aTypeStr == "0")
6358   {
6359     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6360   }
6361   else if (aTypeStr == "short")
6362   {
6363     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Short;
6364   }
6365   else if (aTypeStr == "full"
6366         || aTypeStr == "1")
6367   {
6368     theGlslDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6369   }
6370   else
6371   {
6372     return Standard_False;
6373   }
6374   return Standard_True;
6375 }
6376
6377 //==============================================================================
6378 //function : VGlDebug
6379 //purpose  :
6380 //==============================================================================
6381
6382 static int VGlDebug (Draw_Interpretor& theDI,
6383                      Standard_Integer  theArgNb,
6384                      const char**      theArgVec)
6385 {
6386   Handle(OpenGl_GraphicDriver) aDriver;
6387   Handle(V3d_View) aView = ViewerTest::CurrentView();
6388   if (!aView.IsNull())
6389   {
6390     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aView->Viewer()->Driver());
6391   }
6392   OpenGl_Caps* aDefCaps = &ViewerTest_myDefaultCaps;
6393   OpenGl_Caps* aCaps    = !aDriver.IsNull() ? &aDriver->ChangeOptions() : NULL;
6394
6395   if (theArgNb < 2)
6396   {
6397     TCollection_AsciiString aDebActive, aSyncActive;
6398     if (aCaps == NULL)
6399     {
6400       aCaps = aDefCaps;
6401     }
6402     else
6403     {
6404       Standard_Boolean isActive = OpenGl_Context::CheckExtension ((const char* )::glGetString (GL_EXTENSIONS),
6405                                                                   "GL_ARB_debug_output");
6406       aDebActive = isActive ? " (active)" : " (inactive)";
6407       if (isActive)
6408       {
6409         // GL_DEBUG_OUTPUT_SYNCHRONOUS_ARB
6410         aSyncActive = ::glIsEnabled (0x8242) == GL_TRUE ? " (active)" : " (inactive)";
6411       }
6412     }
6413
6414     TCollection_AsciiString aGlslCodeDebugStatus = TCollection_AsciiString()
6415       + "glslSourceCode: "
6416       + (aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Off
6417          ? "Off"
6418          : aCaps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short
6419           ? "Short"
6420           : "Full")
6421       + "\n";
6422     theDI << "debug:          " << (aCaps->contextDebug      ? "1" : "0") << aDebActive  << "\n"
6423           << "sync:           " << (aCaps->contextSyncDebug  ? "1" : "0") << aSyncActive << "\n"
6424           << "glslWarn:       " << (aCaps->glslWarnings      ? "1" : "0") << "\n"
6425           << aGlslCodeDebugStatus
6426           << "extraMsg:       " << (aCaps->suppressExtraMsg  ? "0" : "1") << "\n";
6427     return 0;
6428   }
6429
6430   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6431   {
6432     Standard_CString        anArg     = theArgVec[anArgIter];
6433     TCollection_AsciiString anArgCase (anArg);
6434     anArgCase.LowerCase();
6435     Standard_Boolean toEnableDebug = Standard_True;
6436     if (anArgCase == "-glsl"
6437      || anArgCase == "-glslwarn"
6438      || anArgCase == "-glslwarns"
6439      || anArgCase == "-glslwarnings")
6440     {
6441       Standard_Boolean toShowWarns = Standard_True;
6442       if (++anArgIter < theArgNb
6443       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShowWarns))
6444       {
6445         --anArgIter;
6446       }
6447       aDefCaps->glslWarnings = toShowWarns;
6448       if (aCaps != NULL)
6449       {
6450         aCaps->glslWarnings = toShowWarns;
6451       }
6452     }
6453     else if (anArgCase == "-extra"
6454           || anArgCase == "-extramsg"
6455           || anArgCase == "-extramessages")
6456     {
6457       Standard_Boolean toShow = Standard_True;
6458       if (++anArgIter < theArgNb
6459       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toShow))
6460       {
6461         --anArgIter;
6462       }
6463       aDefCaps->suppressExtraMsg = !toShow;
6464       if (aCaps != NULL)
6465       {
6466         aCaps->suppressExtraMsg = !toShow;
6467       }
6468     }
6469     else if (anArgCase == "-noextra"
6470           || anArgCase == "-noextramsg"
6471           || anArgCase == "-noextramessages")
6472     {
6473       Standard_Boolean toSuppress = Standard_True;
6474       if (++anArgIter < theArgNb
6475       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSuppress))
6476       {
6477         --anArgIter;
6478       }
6479       aDefCaps->suppressExtraMsg = toSuppress;
6480       if (aCaps != NULL)
6481       {
6482         aCaps->suppressExtraMsg = toSuppress;
6483       }
6484     }
6485     else if (anArgCase == "-sync")
6486     {
6487       Standard_Boolean toSync = Standard_True;
6488       if (++anArgIter < theArgNb
6489       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toSync))
6490       {
6491         --anArgIter;
6492       }
6493       aDefCaps->contextSyncDebug = toSync;
6494       if (toSync)
6495       {
6496         aDefCaps->contextDebug = Standard_True;
6497       }
6498     }
6499     else if (anArgCase == "-glslsourcecode"
6500           || anArgCase == "-glslcode")
6501     {
6502       OpenGl_ShaderProgramDumpLevel aGslsDumpLevel = OpenGl_ShaderProgramDumpLevel_Full;
6503       if (++anArgIter < theArgNb
6504       && !parseGlslSourceFlag (theArgVec[anArgIter], aGslsDumpLevel))
6505       {
6506         --anArgIter;
6507       }
6508       aDefCaps->glslDumpLevel = aGslsDumpLevel;
6509       if (aCaps != NULL)
6510       {
6511         aCaps->glslDumpLevel = aGslsDumpLevel;
6512       }
6513     }
6514     else if (anArgCase == "-debug")
6515     {
6516       if (++anArgIter < theArgNb
6517       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnableDebug))
6518       {
6519         --anArgIter;
6520       }
6521       aDefCaps->contextDebug = toEnableDebug;
6522     }
6523     else if (ViewerTest::ParseOnOff (anArg, toEnableDebug)
6524           && (anArgIter + 1 == theArgNb))
6525     {
6526       // simple alias to turn on almost everything
6527       aDefCaps->contextDebug     = toEnableDebug;
6528       aDefCaps->contextSyncDebug = toEnableDebug;
6529       aDefCaps->glslWarnings     = toEnableDebug;
6530       if (!toEnableDebug)
6531       {
6532         aDefCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6533       }
6534       aDefCaps->suppressExtraMsg = !toEnableDebug;
6535       if (aCaps != NULL)
6536       {
6537         aCaps->contextDebug     = toEnableDebug;
6538         aCaps->contextSyncDebug = toEnableDebug;
6539         aCaps->glslWarnings     = toEnableDebug;
6540         if (!toEnableDebug)
6541         {
6542           aCaps->glslDumpLevel = OpenGl_ShaderProgramDumpLevel_Off;
6543         }
6544         aCaps->suppressExtraMsg = !toEnableDebug;
6545       }
6546     }
6547     else
6548     {
6549       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
6550       return 1;
6551     }
6552   }
6553
6554   return 0;
6555 }
6556
6557 //==============================================================================
6558 //function : VVbo
6559 //purpose  :
6560 //==============================================================================
6561
6562 static int VVbo (Draw_Interpretor& theDI,
6563                  Standard_Integer  theArgNb,
6564                  const char**      theArgVec)
6565 {
6566   const Standard_Boolean toSet    = (theArgNb > 1);
6567   const Standard_Boolean toUseVbo = toSet ? (Draw::Atoi (theArgVec[1]) == 0) : 1;
6568   if (toSet)
6569   {
6570     ViewerTest_myDefaultCaps.vboDisable = toUseVbo;
6571   }
6572
6573   // get the context
6574   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6575   if (aContextAIS.IsNull())
6576   {
6577     if (!toSet)
6578     {
6579       std::cerr << "No active view!\n";
6580     }
6581     return 1;
6582   }
6583   Handle(OpenGl_GraphicDriver) aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContextAIS->CurrentViewer()->Driver());
6584   if (!aDriver.IsNull())
6585   {
6586     if (!toSet)
6587     {
6588       theDI << (aDriver->Options().vboDisable ? "0" : "1") << "\n";
6589     }
6590     else
6591     {
6592       aDriver->ChangeOptions().vboDisable = toUseVbo;
6593     }
6594   }
6595
6596   return 0;
6597 }
6598
6599 //==============================================================================
6600 //function : VCaps
6601 //purpose  :
6602 //==============================================================================
6603
6604 static int VCaps (Draw_Interpretor& theDI,
6605                   Standard_Integer  theArgNb,
6606                   const char**      theArgVec)
6607 {
6608   OpenGl_Caps* aCaps = &ViewerTest_myDefaultCaps;
6609   Handle(OpenGl_GraphicDriver)   aDriver;
6610   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
6611   if (!aContext.IsNull())
6612   {
6613     aDriver = Handle(OpenGl_GraphicDriver)::DownCast (aContext->CurrentViewer()->Driver());
6614     aCaps   = &aDriver->ChangeOptions();
6615   }
6616
6617   if (theArgNb < 2)
6618   {
6619     theDI << "VBO:     " << (aCaps->vboDisable        ? "0" : "1") << "\n";
6620     theDI << "Sprites: " << (aCaps->pntSpritesDisable ? "0" : "1") << "\n";
6621     theDI << "SoftMode:" << (aCaps->contextNoAccel    ? "1" : "0") << "\n";
6622     theDI << "FFP:     " << (aCaps->ffpEnable         ? "1" : "0") << "\n";
6623     theDI << "PolygonMode: " << (aCaps->usePolygonMode ? "1" : "0") << "\n";
6624     theDI << "VSync:   " <<  aCaps->swapInterval                   << "\n";
6625     theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n";
6626     theDI << "Stereo:  " << (aCaps->contextStereo ? "1" : "0") << "\n";
6627     theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n";
6628     return 0;
6629   }
6630
6631   ViewerTest_AutoUpdater anUpdateTool (aContext, ViewerTest::CurrentView());
6632   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
6633   {
6634     Standard_CString        anArg     = theArgVec[anArgIter];
6635     TCollection_AsciiString anArgCase (anArg);
6636     anArgCase.LowerCase();
6637     if (anUpdateTool.parseRedrawMode (anArg))
6638     {
6639       continue;
6640     }
6641     else if (anArgCase == "-vsync"
6642           || anArgCase == "-swapinterval")
6643     {
6644       Standard_Boolean toEnable = Standard_True;
6645       if (++anArgIter < theArgNb
6646       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6647       {
6648         --anArgIter;
6649       }
6650       aCaps->swapInterval = toEnable;
6651     }
6652     else if (anArgCase == "-ffp")
6653     {
6654       Standard_Boolean toEnable = Standard_True;
6655       if (++anArgIter < theArgNb
6656       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6657       {
6658         --anArgIter;
6659       }
6660       aCaps->ffpEnable = toEnable;
6661     }
6662     else if (anArgCase == "-polygonmode")
6663     {
6664       Standard_Boolean toEnable = Standard_True;
6665       if (++anArgIter < theArgNb
6666       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6667       {
6668         --anArgIter;
6669       }
6670       aCaps->usePolygonMode = toEnable;
6671     }
6672     else if (anArgCase == "-vbo")
6673     {
6674       Standard_Boolean toEnable = Standard_True;
6675       if (++anArgIter < theArgNb
6676       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6677       {
6678         --anArgIter;
6679       }
6680       aCaps->vboDisable = !toEnable;
6681     }
6682     else if (anArgCase == "-sprite"
6683           || anArgCase == "-sprites")
6684     {
6685       Standard_Boolean toEnable = Standard_True;
6686       if (++anArgIter < theArgNb
6687       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6688       {
6689         --anArgIter;
6690       }
6691       aCaps->pntSpritesDisable = !toEnable;
6692     }
6693     else if (anArgCase == "-softmode")
6694     {
6695       Standard_Boolean toEnable = Standard_True;
6696       if (++anArgIter < theArgNb
6697       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6698       {
6699         --anArgIter;
6700       }
6701       aCaps->contextNoAccel = toEnable;
6702     }
6703     else if (anArgCase == "-winbuffer"
6704           || anArgCase == "-windowbuffer"
6705           || anArgCase == "-usewinbuffer"
6706           || anArgCase == "-usewindowbuffer"
6707           || anArgCase == "-usesystembuffer")
6708     {
6709       Standard_Boolean toEnable = Standard_True;
6710       if (++anArgIter < theArgNb
6711       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6712       {
6713         --anArgIter;
6714       }
6715       aCaps->useSystemBuffer = toEnable;
6716     }
6717     else if (anArgCase == "-accel"
6718           || anArgCase == "-acceleration")
6719     {
6720       Standard_Boolean toEnable = Standard_True;
6721       if (++anArgIter < theArgNb
6722       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6723       {
6724         --anArgIter;
6725       }
6726       aCaps->contextNoAccel = !toEnable;
6727     }
6728     else if (anArgCase == "-compat"
6729           || anArgCase == "-compatprofile"
6730           || anArgCase == "-compatible"
6731           || anArgCase == "-compatibleprofile")
6732     {
6733       Standard_Boolean toEnable = Standard_True;
6734       if (++anArgIter < theArgNb
6735       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6736       {
6737         --anArgIter;
6738       }
6739       aCaps->contextCompatible = toEnable;
6740       if (!aCaps->contextCompatible)
6741       {
6742         aCaps->ffpEnable = Standard_False;
6743       }
6744     }
6745     else if (anArgCase == "-core"
6746           || anArgCase == "-coreprofile")
6747     {
6748       Standard_Boolean toEnable = Standard_True;
6749       if (++anArgIter < theArgNb
6750       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6751       {
6752         --anArgIter;
6753       }
6754       aCaps->contextCompatible = !toEnable;
6755       if (!aCaps->contextCompatible)
6756       {
6757         aCaps->ffpEnable = Standard_False;
6758       }
6759     }
6760     else if (anArgCase == "-stereo"
6761           || anArgCase == "-quadbuffer")
6762     {
6763       Standard_Boolean toEnable = Standard_True;
6764       if (++anArgIter < theArgNb
6765       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
6766       {
6767         --anArgIter;
6768       }
6769       aCaps->contextStereo = toEnable;
6770     }
6771     else
6772     {
6773       std::cout << "Error: unknown argument '" << anArg << "'\n";
6774       return 1;
6775     }
6776   }
6777   if (aCaps != &ViewerTest_myDefaultCaps)
6778   {
6779     ViewerTest_myDefaultCaps = *aCaps;
6780   }
6781   return 0;
6782 }
6783
6784 //==============================================================================
6785 //function : VMemGpu
6786 //purpose  :
6787 //==============================================================================
6788
6789 static int VMemGpu (Draw_Interpretor& theDI,
6790                     Standard_Integer  theArgNb,
6791                     const char**      theArgVec)
6792 {
6793   // get the context
6794   Handle(AIS_InteractiveContext) aContextAIS = ViewerTest::GetAISContext();
6795   if (aContextAIS.IsNull())
6796   {
6797     std::cerr << "No active view. Please call vinit.\n";
6798     return 1;
6799   }
6800
6801   Handle(Graphic3d_GraphicDriver) aDriver = aContextAIS->CurrentViewer()->Driver();
6802   if (aDriver.IsNull())
6803   {
6804     std::cerr << "Graphic driver not available.\n";
6805     return 1;
6806   }
6807
6808   Standard_Size aFreeBytes = 0;
6809   TCollection_AsciiString anInfo;
6810   if (!aDriver->MemoryInfo (aFreeBytes, anInfo))
6811   {
6812     std::cerr << "Information not available.\n";
6813     return 1;
6814   }
6815
6816   if (theArgNb > 1 && *theArgVec[1] == 'f')
6817   {
6818     theDI << Standard_Real (aFreeBytes);
6819   }
6820   else
6821   {
6822     theDI << anInfo;
6823   }
6824
6825   return 0;
6826 }
6827
6828 // ==============================================================================
6829 // function : VReadPixel
6830 // purpose  :
6831 // ==============================================================================
6832 static int VReadPixel (Draw_Interpretor& theDI,
6833                        Standard_Integer  theArgNb,
6834                        const char**      theArgVec)
6835 {
6836   // get the active view
6837   Handle(V3d_View) aView = ViewerTest::CurrentView();
6838   if (aView.IsNull())
6839   {
6840     std::cerr << "No active view. Please call vinit.\n";
6841     return 1;
6842   }
6843   else if (theArgNb < 3)
6844   {
6845     std::cerr << "Usage : " << theArgVec[0] << " xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [name]\n";
6846     return 1;
6847   }
6848
6849   Image_Format         aFormat     = Image_Format_RGBA;
6850   Graphic3d_BufferType aBufferType = Graphic3d_BT_RGBA;
6851
6852   Standard_Integer aWidth, aHeight;
6853   aView->Window()->Size (aWidth, aHeight);
6854   const Standard_Integer anX = Draw::Atoi (theArgVec[1]);
6855   const Standard_Integer anY = Draw::Atoi (theArgVec[2]);
6856   if (anX < 0 || anX >= aWidth || anY < 0 || anY > aHeight)
6857   {
6858     std::cerr << "Pixel coordinates (" << anX << "; " << anY << ") are out of view (" << aWidth << " x " << aHeight << ")\n";
6859     return 1;
6860   }
6861
6862   Standard_Boolean toShowName = Standard_False;
6863   Standard_Boolean toShowHls  = Standard_False;
6864   for (Standard_Integer anIter = 3; anIter < theArgNb; ++anIter)
6865   {
6866     TCollection_AsciiString aParam (theArgVec[anIter]);
6867     aParam.LowerCase();
6868     if (aParam == "-rgb"
6869      || aParam == "rgb")
6870     {
6871       aFormat     = Image_Format_RGB;
6872       aBufferType = Graphic3d_BT_RGB;
6873     }
6874     else if (aParam == "-hls"
6875           || aParam == "hls")
6876     {
6877       aFormat     = Image_Format_RGB;
6878       aBufferType = Graphic3d_BT_RGB;
6879       toShowHls   = Standard_True;
6880     }
6881     else if (aParam == "-rgbf"
6882           || aParam == "rgbf")
6883     {
6884       aFormat     = Image_Format_RGBF;
6885       aBufferType = Graphic3d_BT_RGB;
6886     }
6887     else if (aParam == "-rgba"
6888           || aParam == "rgba")
6889     {
6890       aFormat     = Image_Format_RGBA;
6891       aBufferType = Graphic3d_BT_RGBA;
6892     }
6893     else if (aParam == "-rgbaf"
6894           || aParam == "rgbaf")
6895     {
6896       aFormat     = Image_Format_RGBAF;
6897       aBufferType = Graphic3d_BT_RGBA;
6898     }
6899     else if (aParam == "-depth"
6900           || aParam == "depth")
6901     {
6902       aFormat     = Image_Format_GrayF;
6903       aBufferType = Graphic3d_BT_Depth;
6904     }
6905     else if (aParam == "-name"
6906           || aParam == "name")
6907     {
6908       toShowName = Standard_True;
6909     }
6910     else
6911     {
6912       std::cout << "Syntax error at '" << aParam << "'\n";
6913     }
6914   }
6915
6916   Image_PixMap anImage;
6917   if (!anImage.InitTrash (aFormat, aWidth, aHeight))
6918   {
6919     std::cerr << "Image allocation failed\n";
6920     return 1;
6921   }
6922   else if (!aView->ToPixMap (anImage, aWidth, aHeight, aBufferType))
6923   {
6924     std::cerr << "Image dump failed\n";
6925     return 1;
6926   }
6927
6928   // redirect possible warning messages that could have been added by ToPixMap
6929   // into the Tcl interpretor (via DefaultMessenger) to cout, so that they do not
6930   // contaminate result of the command
6931   Standard_CString aWarnLog = theDI.Result();
6932   if (aWarnLog != NULL && aWarnLog[0] != '\0')
6933   {
6934     std::cout << aWarnLog << std::endl;
6935   }
6936   theDI.Reset();
6937
6938   Quantity_ColorRGBA aColor = anImage.PixelColor (anX, anY);
6939   if (toShowName)
6940   {
6941     if (aBufferType == Graphic3d_BT_RGBA)
6942     {
6943       theDI << Quantity_Color::StringName (aColor.GetRGB().Name()) << " " << aColor.Alpha();
6944     }
6945     else
6946     {
6947       theDI << Quantity_Color::StringName (aColor.GetRGB().Name());
6948     }
6949   }
6950   else
6951   {
6952     switch (aBufferType)
6953     {
6954       default:
6955       case Graphic3d_BT_RGB:
6956       {
6957         if (toShowHls)
6958         {
6959           theDI << aColor.GetRGB().Hue() << " " << aColor.GetRGB().Light() << " " << aColor.GetRGB().Saturation();
6960         }
6961         else
6962         {
6963           theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue();
6964         }
6965         break;
6966       }
6967       case Graphic3d_BT_RGBA:
6968       {
6969         theDI << aColor.GetRGB().Red() << " " << aColor.GetRGB().Green() << " " << aColor.GetRGB().Blue() << " " << aColor.Alpha();
6970         break;
6971       }
6972       case Graphic3d_BT_Depth:
6973       {
6974         theDI << aColor.GetRGB().Red();
6975         break;
6976       }
6977     }
6978   }
6979
6980   return 0;
6981 }
6982
6983 //! Auxiliary presentation for an image plane.
6984 class ViewerTest_ImagePrs : public AIS_InteractiveObject
6985 {
6986 public:
6987   //! Main constructor.
6988   ViewerTest_ImagePrs (const Handle(Image_PixMap)& theImage,
6989                        const Standard_Real theWidth,
6990                        const Standard_Real theHeight,
6991                        const TCollection_AsciiString& theLabel)
6992   : myLabel (theLabel), myWidth (theWidth), myHeight(theHeight)
6993   {
6994     SetDisplayMode (0);
6995     SetHilightMode (1);
6996     myDynHilightDrawer->SetZLayer (Graphic3d_ZLayerId_Topmost);
6997     {
6998       myDrawer->SetShadingAspect (new Prs3d_ShadingAspect());
6999       const Handle(Graphic3d_AspectFillArea3d)& aFillAspect = myDrawer->ShadingAspect()->Aspect();
7000       Graphic3d_MaterialAspect aMat;
7001       aMat.SetMaterialType (Graphic3d_MATERIAL_PHYSIC);
7002       aMat.SetAmbient  (1.0);
7003       aMat.SetDiffuse  (1.0);
7004       aMat.SetSpecular (1.0);
7005       aMat.SetEmissive (1.0);
7006       aMat.SetReflectionModeOn (Graphic3d_TOR_AMBIENT);
7007       aMat.SetReflectionModeOn (Graphic3d_TOR_DIFFUSE);
7008       aMat.SetReflectionModeOn (Graphic3d_TOR_SPECULAR);
7009       aMat.SetReflectionModeOn (Graphic3d_TOR_EMISSION);
7010       aMat.SetAmbientColor  (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7011       aMat.SetDiffuseColor  (Quantity_Color (1.0, 1.0, 1.0, Quantity_TOC_RGB));
7012       aMat.SetSpecularColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7013       aMat.SetEmissiveColor (Quantity_Color (0.0, 0.0, 0.0, Quantity_TOC_RGB));
7014       aFillAspect->SetFrontMaterial (aMat);
7015       aFillAspect->SetTextureMap (new Graphic3d_Texture2Dmanual (theImage));
7016       aFillAspect->SetTextureMapOn();
7017     }
7018     {
7019       Handle(Prs3d_TextAspect) aTextAspect = new Prs3d_TextAspect();
7020       aTextAspect->SetHorizontalJustification (Graphic3d_HTA_CENTER);
7021       aTextAspect->SetVerticalJustification   (Graphic3d_VTA_CENTER);
7022       myDrawer->SetTextAspect (aTextAspect);
7023     }
7024     {
7025       const gp_Dir aNorm (0.0, 0.0, 1.0);
7026       myTris = new Graphic3d_ArrayOfTriangles (4, 6, true, false, true);
7027       myTris->AddVertex (gp_Pnt(-myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 0.0));
7028       myTris->AddVertex (gp_Pnt( myWidth * 0.5, -myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 0.0));
7029       myTris->AddVertex (gp_Pnt(-myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (0.0, 1.0));
7030       myTris->AddVertex (gp_Pnt( myWidth * 0.5,  myHeight * 0.5, 0.0), aNorm, gp_Pnt2d (1.0, 1.0));
7031       myTris->AddEdge (1);
7032       myTris->AddEdge (2);
7033       myTris->AddEdge (3);
7034       myTris->AddEdge (3);
7035       myTris->AddEdge (2);
7036       myTris->AddEdge (4);
7037
7038       myRect = new Graphic3d_ArrayOfPolylines (4);
7039       myRect->AddVertex (myTris->Vertice (1));
7040       myRect->AddVertex (myTris->Vertice (3));
7041       myRect->AddVertex (myTris->Vertice (4));
7042       myRect->AddVertex (myTris->Vertice (2));
7043     }
7044   }
7045
7046   //! Returns TRUE for accepted display modes.
7047   virtual Standard_Boolean AcceptDisplayMode (const Standard_Integer theMode) const Standard_OVERRIDE { return theMode == 0 || theMode == 1; }
7048
7049   //! Compute presentation.
7050   virtual void Compute (const Handle(PrsMgr_PresentationManager3d)& , const Handle(Prs3d_Presentation)& thePrs, const Standard_Integer theMode) Standard_OVERRIDE
7051   {
7052     switch (theMode)
7053     {
7054       case 0:
7055       {
7056         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7057         aGroup->AddPrimitiveArray (myTris);
7058         aGroup->SetGroupPrimitivesAspect (myDrawer->ShadingAspect()->Aspect());
7059         aGroup->AddPrimitiveArray (myRect);
7060         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7061         return;
7062       }
7063       case 1:
7064       {
7065         Prs3d_Text::Draw (thePrs->NewGroup(), myDrawer->TextAspect(), myLabel, gp_Pnt(0.0, 0.0, 0.0));
7066         Handle(Graphic3d_Group) aGroup = thePrs->NewGroup();
7067         aGroup->AddPrimitiveArray (myRect);
7068         aGroup->SetGroupPrimitivesAspect (myDrawer->LineAspect()->Aspect());
7069         return;
7070       }
7071     }
7072   }
7073
7074   //! Compute selection.
7075   virtual void ComputeSelection (const Handle(SelectMgr_Selection)& theSel, const Standard_Integer theMode) Standard_OVERRIDE
7076   {
7077     if (theMode == 0)
7078     {
7079       Handle(SelectMgr_EntityOwner) anEntityOwner = new SelectMgr_EntityOwner (this, 5);
7080       Handle(Select3D_SensitivePrimitiveArray) aSensitive = new Select3D_SensitivePrimitiveArray (anEntityOwner);
7081       aSensitive->InitTriangulation (myTris->Attributes(), myTris->Indices(), TopLoc_Location());
7082       theSel->Add (aSensitive);
7083     }
7084   }
7085
7086 private:
7087   Handle(Graphic3d_ArrayOfTriangles) myTris;
7088   Handle(Graphic3d_ArrayOfPolylines) myRect;
7089   TCollection_AsciiString myLabel;
7090   Standard_Real myWidth;
7091   Standard_Real myHeight;
7092 };
7093
7094 //==============================================================================
7095 //function : VDiffImage
7096 //purpose  : The draw-command compares two images.
7097 //==============================================================================
7098
7099 static int VDiffImage (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
7100 {
7101   if (theArgNb < 3)
7102   {
7103     std::cout << "Syntax error: not enough arguments.\n";
7104     return 1;
7105   }
7106
7107   Standard_Integer anArgIter = 1;
7108   TCollection_AsciiString anImgPathRef (theArgVec[anArgIter++]);
7109   TCollection_AsciiString anImgPathNew (theArgVec[anArgIter++]);
7110   TCollection_AsciiString aDiffImagePath;
7111   Standard_Real    aTolColor        = -1.0;
7112   Standard_Integer toBlackWhite     = -1;
7113   Standard_Integer isBorderFilterOn = -1;
7114   Standard_Boolean isOldSyntax = Standard_False;
7115   TCollection_AsciiString aViewName, aPrsNameRef, aPrsNameNew, aPrsNameDiff;
7116   for (; anArgIter < theArgNb; ++anArgIter)
7117   {
7118     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7119     anArg.LowerCase();
7120     if (anArgIter + 1 < theArgNb
7121      && (anArg == "-toleranceofcolor"
7122       || anArg == "-tolerancecolor"
7123       || anArg == "-tolerance"
7124       || anArg == "-toler"))
7125     {
7126       aTolColor = Atof (theArgVec[++anArgIter]);
7127       if (aTolColor < 0.0 || aTolColor > 1.0)
7128       {
7129         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7130         return 1;
7131       }
7132     }
7133     else if (anArg == "-blackwhite")
7134     {
7135       Standard_Boolean toEnable = Standard_True;
7136       if (anArgIter + 1 < theArgNb
7137        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7138       {
7139         ++anArgIter;
7140       }
7141       toBlackWhite = toEnable ? 1 : 0;
7142     }
7143     else if (anArg == "-borderfilter")
7144     {
7145       Standard_Boolean toEnable = Standard_True;
7146       if (anArgIter + 1 < theArgNb
7147        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
7148       {
7149         ++anArgIter;
7150       }
7151       isBorderFilterOn = toEnable ? 1 : 0;
7152     }
7153     else if (anArg == "-exitonclose")
7154     {
7155       ViewerTest_EventManager::ToExitOnCloseView() = true;
7156       if (anArgIter + 1 < theArgNb
7157        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToExitOnCloseView()))
7158       {
7159         ++anArgIter;
7160       }
7161     }
7162     else if (anArg == "-closeonescape"
7163           || anArg == "-closeonesc")
7164     {
7165       ViewerTest_EventManager::ToCloseViewOnEscape() = true;
7166       if (anArgIter + 1 < theArgNb
7167        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
7168       {
7169         ++anArgIter;
7170       }
7171     }
7172     else if (anArgIter + 3 < theArgNb
7173           && anArg == "-display")
7174     {
7175       aViewName   = theArgVec[++anArgIter];
7176       aPrsNameRef = theArgVec[++anArgIter];
7177       aPrsNameNew = theArgVec[++anArgIter];
7178       if (anArgIter + 1 < theArgNb
7179       && *theArgVec[anArgIter + 1] != '-')
7180       {
7181         aPrsNameDiff = theArgVec[++anArgIter];
7182       }
7183     }
7184     else if (aTolColor < 0.0
7185           && anArg.IsRealValue())
7186     {
7187       isOldSyntax = Standard_True;
7188       aTolColor = anArg.RealValue();
7189       if (aTolColor < 0.0 || aTolColor > 1.0)
7190       {
7191         std::cout << "Syntax error at '" << anArg << " " << theArgVec[anArgIter] << "'\n";
7192         return 1;
7193       }
7194     }
7195     else if (isOldSyntax
7196           && toBlackWhite == -1
7197           && (anArg == "0" || anArg == "1"))
7198     {
7199       toBlackWhite = anArg == "1" ? 1 : 0;
7200     }
7201     else if (isOldSyntax
7202           && isBorderFilterOn == -1
7203           && (anArg == "0" || anArg == "1"))
7204     {
7205       isBorderFilterOn = anArg == "1" ? 1 : 0;
7206     }
7207     else if (aDiffImagePath.IsEmpty())
7208     {
7209       aDiffImagePath = theArgVec[anArgIter];
7210     }
7211     else
7212     {
7213       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7214       return 1;
7215     }
7216   }
7217
7218   Handle(Image_AlienPixMap) anImgRef = new Image_AlienPixMap();
7219   Handle(Image_AlienPixMap) anImgNew = new Image_AlienPixMap();
7220   if (!anImgRef->Load (anImgPathRef))
7221   {
7222     std::cout << "Error: image file '" << anImgPathRef << "' cannot be read\n";
7223     return 1;
7224   }
7225   if (!anImgNew->Load (anImgPathNew))
7226   {
7227     std::cout << "Error: image file '" << anImgPathNew << "' cannot be read\n";
7228     return 1;
7229   }
7230
7231   // compare the images
7232   Image_Diff aComparer;
7233   Standard_Integer aDiffColorsNb = -1;
7234   if (aComparer.Init (anImgRef, anImgNew, toBlackWhite == 1))
7235   {
7236     aComparer.SetColorTolerance (aTolColor >= 0.0 ? aTolColor : 0.0);
7237     aComparer.SetBorderFilterOn (isBorderFilterOn == 1);
7238     aDiffColorsNb = aComparer.Compare();
7239     theDI << aDiffColorsNb << "\n";
7240   }
7241
7242   // save image of difference
7243   Handle(Image_AlienPixMap) aDiff;
7244   if (aDiffColorsNb > 0
7245   && (!aDiffImagePath.IsEmpty() || !aPrsNameDiff.IsEmpty()))
7246   {
7247     aDiff = new Image_AlienPixMap();
7248     if (!aDiff->InitTrash (Image_Format_Gray, anImgRef->SizeX(), anImgRef->SizeY()))
7249     {
7250       std::cout << "Error: cannot allocate memory for diff image " << anImgRef->SizeX() << "x" << anImgRef->SizeY() << "\n";
7251       return 1;
7252     }
7253     aComparer.SaveDiffImage (*aDiff);
7254     if (!aDiffImagePath.IsEmpty()
7255      && !aDiff->Save (aDiffImagePath))
7256     {
7257       std::cout << "Error: diff image file '" << aDiffImagePath << "' cannot be written\n";
7258       return 1;
7259     }
7260   }
7261
7262   if (aViewName.IsEmpty())
7263   {
7264     return 0;
7265   }
7266
7267   ViewerTest_Names aViewNames (aViewName);
7268   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
7269   {
7270     TCollection_AsciiString aCommand = TCollection_AsciiString ("vclose ") + aViewNames.GetViewName();
7271     theDI.Eval (aCommand.ToCString());
7272   }
7273
7274   Standard_Integer aPxLeft = 0;
7275   Standard_Integer aPxTop  = 0;
7276   Standard_Integer aWinSizeX = int(anImgRef->SizeX() * 2);
7277   Standard_Integer aWinSizeY = !aDiff.IsNull() && !aPrsNameDiff.IsEmpty()
7278                               ? int(anImgRef->SizeY() * 2)
7279                               : int(anImgRef->SizeY());
7280   TCollection_AsciiString aDisplayName;
7281   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aWinSizeX, aWinSizeY,
7282                                                             aViewName, aDisplayName);
7283
7284   Standard_Real aRatio = anImgRef->Ratio();
7285   Standard_Real aSizeX = 1.0;
7286   Standard_Real aSizeY = aSizeX / aRatio;
7287   {
7288     OSD_Path aPath (anImgPathRef);
7289     TCollection_AsciiString aLabelRef;
7290     if (!aPath.Name().IsEmpty())
7291     {
7292       aLabelRef = aPath.Name() + aPath.Extension();
7293     }
7294     aLabelRef += TCollection_AsciiString() + "\n" + int(anImgRef->SizeX()) + "x" + int(anImgRef->SizeY());
7295
7296     Handle(ViewerTest_ImagePrs) anImgRefPrs = new ViewerTest_ImagePrs (anImgRef, aSizeX, aSizeY, aLabelRef);
7297     gp_Trsf aTrsfRef;
7298     aTrsfRef.SetTranslationPart (gp_Vec (-aSizeX * 0.5, 0.0, 0.0));
7299     anImgRefPrs->SetLocalTransformation (aTrsfRef);
7300     ViewerTest::Display (aPrsNameRef, anImgRefPrs, false, true);
7301   }
7302   {
7303     OSD_Path aPath (anImgPathNew);
7304     TCollection_AsciiString aLabelNew;
7305     if (!aPath.Name().IsEmpty())
7306     {
7307       aLabelNew = aPath.Name() + aPath.Extension();
7308     }
7309     aLabelNew += TCollection_AsciiString() + "\n" + int(anImgNew->SizeX()) + "x" + int(anImgNew->SizeY());
7310
7311     Handle(ViewerTest_ImagePrs) anImgNewPrs = new ViewerTest_ImagePrs (anImgNew, aSizeX, aSizeY, aLabelNew);
7312     gp_Trsf aTrsfRef;
7313     aTrsfRef.SetTranslationPart (gp_Vec (aSizeX * 0.5, 0.0, 0.0));
7314     anImgNewPrs->SetLocalTransformation (aTrsfRef);
7315     ViewerTest::Display (aPrsNameNew, anImgNewPrs, false, true);
7316   }
7317   Handle(ViewerTest_ImagePrs) anImgDiffPrs;
7318   if (!aDiff.IsNull())
7319   {
7320     anImgDiffPrs = new ViewerTest_ImagePrs (aDiff, aSizeX, aSizeY, TCollection_AsciiString() + "Difference: " + aDiffColorsNb + " pixels");
7321     gp_Trsf aTrsfDiff;
7322     aTrsfDiff.SetTranslationPart (gp_Vec (0.0, -aSizeY, 0.0));
7323     anImgDiffPrs->SetLocalTransformation (aTrsfDiff);
7324   }
7325   if (!aPrsNameDiff.IsEmpty())
7326   {
7327     ViewerTest::Display (aPrsNameDiff, anImgDiffPrs, false, true);
7328   }
7329   ViewerTest::CurrentView()->SetProj (V3d_Zpos);
7330   ViewerTest::CurrentView()->FitAll();
7331   return 0;
7332 }
7333
7334 //=======================================================================
7335 //function : VSelect
7336 //purpose  : Emulates different types of selection by mouse:
7337 //           1) single click selection
7338 //           2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)
7339 //           3) selection with polygon having corners at
7340 //           pixel positions (x1,y1),...,(xn,yn)
7341 //           4) any of these selections with shift button pressed
7342 //=======================================================================
7343 static Standard_Integer VSelect (Draw_Interpretor& ,
7344                                  Standard_Integer theNbArgs,
7345                                  const char** theArgVec)
7346 {
7347   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
7348   if (aCtx.IsNull())
7349   {
7350     std::cout << "Error: no active View\n";
7351     return 1;
7352   }
7353
7354   NCollection_Sequence<Graphic3d_Vec2i> aPnts;
7355   bool isShiftSelection = false, toAllowOverlap = false;
7356   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7357   {
7358     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7359     anArg.LowerCase();
7360     if (anArg == "-allowoverlap")
7361     {
7362       toAllowOverlap = true;
7363       if (anArgIter + 1 < theNbArgs
7364        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toAllowOverlap))
7365       {
7366         ++anArgIter;
7367       }
7368     }
7369     else if (anArgIter + 1 < theNbArgs
7370           && anArg.IsIntegerValue()
7371           && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
7372     {
7373       const TCollection_AsciiString anArgNext (theArgVec[++anArgIter]);
7374       aPnts.Append (Graphic3d_Vec2i (anArg.IntegerValue(), anArgNext.IntegerValue()));
7375     }
7376     else if (anArgIter + 1 == theNbArgs
7377           && anArg.IsIntegerValue())
7378     {
7379       isShiftSelection = anArg.IntegerValue() == 1;
7380     }
7381     else
7382     {
7383       std::cout << "Syntax error at '" << anArg << "'\n";
7384       return 1;
7385     }
7386   }
7387   if (toAllowOverlap
7388    && aPnts.Length() != 2)
7389   {
7390     std::cout << "Syntax error: -allowoverlap key is applied only for rectangle selection\n";
7391     return 1;
7392   }
7393   if (toAllowOverlap)
7394   {
7395     aCtx->MainSelector()->AllowOverlapDetection (toAllowOverlap);
7396   }
7397
7398   Handle(ViewerTest_EventManager) aCurrentEventManager = ViewerTest::CurrentEventManager();
7399   if (aPnts.IsEmpty())
7400   {
7401     if (isShiftSelection)
7402     {
7403       aCtx->ShiftSelect (false);
7404     }
7405     else
7406     {
7407       aCtx->Select (false);
7408     }
7409     aCtx->CurrentViewer()->Invalidate();
7410   }
7411   else if (aPnts.Length() == 2)
7412   {
7413     if (toAllowOverlap
7414      && aPnts.First().y() < aPnts.Last().y())
7415     {
7416       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7417     }
7418     else if (!toAllowOverlap
7419            && aPnts.First().y() > aPnts.Last().y())
7420     {
7421       std::swap (aPnts.ChangeFirst(), aPnts.ChangeLast());
7422     }
7423     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7424   }
7425   else
7426   {
7427     aCurrentEventManager->SelectInViewer (aPnts, isShiftSelection);
7428   }
7429   aCurrentEventManager->FlushViewEvents (aCtx, ViewerTest::CurrentView(), true);
7430   return 0;
7431 }
7432
7433 //=======================================================================
7434 //function : VMoveTo
7435 //purpose  : Emulates cursor movement to defined pixel position
7436 //=======================================================================
7437 static Standard_Integer VMoveTo (Draw_Interpretor& theDI,
7438                                 Standard_Integer theNbArgs,
7439                                 const char**     theArgVec)
7440 {
7441   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
7442   const Handle(V3d_View)&               aView    = ViewerTest::CurrentView();
7443   if (aContext.IsNull())
7444   {
7445     std::cout << "Error: no active View\n";
7446     return 1;
7447   }
7448
7449   Graphic3d_Vec2i aMousePos (IntegerLast(), IntegerLast());
7450   for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
7451   {
7452     TCollection_AsciiString anArgStr (theArgVec[anArgIter]);
7453     anArgStr.LowerCase();
7454     if (anArgStr == "-reset"
7455      || anArgStr == "-clear")
7456     {
7457       if (anArgIter + 1 < theNbArgs)
7458       {
7459         std::cout << "Syntax error at '" << theArgVec[anArgIter + 1] << "'\n";
7460         return 1;
7461       }
7462
7463       const Standard_Boolean toEchoGrid = aContext->CurrentViewer()->Grid()->IsActive()
7464                                        && aContext->CurrentViewer()->GridEcho();
7465       if (toEchoGrid)
7466       {
7467         aContext->CurrentViewer()->HideGridEcho (aView);
7468       }
7469       if (aContext->ClearDetected() || toEchoGrid)
7470       {
7471         aContext->CurrentViewer()->RedrawImmediate();
7472       }
7473       return 0;
7474     }
7475     else if (aMousePos.x() == IntegerLast()
7476           && anArgStr.IsIntegerValue())
7477     {
7478       aMousePos.x() = anArgStr.IntegerValue();
7479     }
7480     else if (aMousePos.y() == IntegerLast()
7481           && anArgStr.IsIntegerValue())
7482     {
7483       aMousePos.y() = anArgStr.IntegerValue();
7484     }
7485     else
7486     {
7487       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
7488       return 1;
7489     }
7490   }
7491
7492   if (aMousePos.x() == IntegerLast()
7493    || aMousePos.y() == IntegerLast())
7494   {
7495     std::cout << "Syntax error: wrong number of arguments\n";
7496     return 1;
7497   }
7498
7499   ViewerTest::CurrentEventManager()->ResetPreviousMoveTo();
7500   ViewerTest::CurrentEventManager()->UpdateMousePosition (aMousePos, Aspect_VKeyMouse_NONE, Aspect_VKeyFlags_NONE, false);
7501   ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
7502
7503   gp_Pnt aTopPnt (RealLast(), RealLast(), RealLast());
7504   const Handle(SelectMgr_EntityOwner)& aDetOwner = aContext->DetectedOwner();
7505   for (Standard_Integer aDetIter = 1; aDetIter <= aContext->MainSelector()->NbPicked(); ++aDetIter)
7506   {
7507     if (aContext->MainSelector()->Picked (aDetIter) == aDetOwner)
7508     {
7509       aTopPnt = aContext->MainSelector()->PickedPoint (aDetIter);
7510       break;
7511     }
7512   }
7513   theDI << aTopPnt.X() << " " << aTopPnt.Y() << " " << aTopPnt.Z();
7514   return 0;
7515 }
7516
7517 namespace
7518 {
7519   //! Global map storing all animations registered in ViewerTest.
7520   static NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)> ViewerTest_AnimationTimelineMap;
7521
7522   //! The animation calling the Draw Harness command.
7523   class ViewerTest_AnimationProc : public AIS_Animation
7524   {
7525   public:
7526
7527     //! Main constructor.
7528     ViewerTest_AnimationProc (const TCollection_AsciiString& theAnimationName,
7529                               Draw_Interpretor* theDI,
7530                               const TCollection_AsciiString& theCommand)
7531     : AIS_Animation (theAnimationName),
7532       myDrawInter(theDI),
7533       myCommand  (theCommand)
7534     {
7535       //
7536     }
7537
7538   protected:
7539
7540     //! Evaluate the command.
7541     virtual void update (const AIS_AnimationProgress& theProgress) Standard_OVERRIDE
7542     {
7543       TCollection_AsciiString aCmd = myCommand;
7544       replace (aCmd, "%pts",             TCollection_AsciiString(theProgress.Pts));
7545       replace (aCmd, "%localpts",        TCollection_AsciiString(theProgress.LocalPts));
7546       replace (aCmd, "%ptslocal",        TCollection_AsciiString(theProgress.LocalPts));
7547       replace (aCmd, "%normalized",      TCollection_AsciiString(theProgress.LocalNormalized));
7548       replace (aCmd, "%localnormalized", TCollection_AsciiString(theProgress.LocalNormalized));
7549       myDrawInter->Eval (aCmd.ToCString());
7550     }
7551
7552     //! Find the keyword in the command and replace it with value.
7553     //! @return the position of the keyword to pass value
7554     void replace (TCollection_AsciiString&       theCmd,
7555                   const TCollection_AsciiString& theKey,
7556                   const TCollection_AsciiString& theVal)
7557     {
7558       TCollection_AsciiString aCmd (theCmd);
7559       aCmd.LowerCase();
7560       const Standard_Integer aPos = aCmd.Search (theKey);
7561       if (aPos == -1)
7562       {
7563         return;
7564       }
7565
7566       TCollection_AsciiString aPart1, aPart2;
7567       Standard_Integer aPart1To = aPos - 1;
7568       if (aPart1To >= 1
7569        && aPart1To <= theCmd.Length())
7570       {
7571         aPart1 = theCmd.SubString (1, aPart1To);
7572       }
7573
7574       Standard_Integer aPart2From = aPos + theKey.Length();
7575       if (aPart2From >= 1
7576        && aPart2From <= theCmd.Length())
7577       {
7578         aPart2 = theCmd.SubString (aPart2From, theCmd.Length());
7579       }
7580
7581       theCmd = aPart1 + theVal + aPart2;
7582     }
7583
7584   protected:
7585
7586     Draw_Interpretor*       myDrawInter;
7587     TCollection_AsciiString myCommand;
7588
7589   };
7590
7591   //! Replace the animation with the new one.
7592   static void replaceAnimation (const Handle(AIS_Animation)& theParentAnimation,
7593                                 Handle(AIS_Animation)&       theAnimation,
7594                                 const Handle(AIS_Animation)& theAnimationNew)
7595   {
7596     theAnimationNew->CopyFrom (theAnimation);
7597     if (!theParentAnimation.IsNull())
7598     {
7599       theParentAnimation->Replace (theAnimation, theAnimationNew);
7600     }
7601     else
7602     {
7603       ViewerTest_AnimationTimelineMap.UnBind (theAnimationNew->Name());
7604       ViewerTest_AnimationTimelineMap.Bind   (theAnimationNew->Name(), theAnimationNew);
7605     }
7606     theAnimation = theAnimationNew;
7607   }
7608
7609   //! Parse the point.
7610   static Standard_Boolean parseXYZ (const char** theArgVec, gp_XYZ& thePnt)
7611   {
7612     const TCollection_AsciiString anXYZ[3] = { theArgVec[0], theArgVec[1], theArgVec[2] };
7613     if (!anXYZ[0].IsRealValue()
7614      || !anXYZ[1].IsRealValue()
7615      || !anXYZ[2].IsRealValue())
7616     {
7617       return Standard_False;
7618     }
7619
7620     thePnt.SetCoord (anXYZ[0].RealValue(), anXYZ[1].RealValue(), anXYZ[2].RealValue());
7621     return Standard_True;
7622   }
7623
7624   //! Parse the quaternion.
7625   static Standard_Boolean parseQuaternion (const char** theArgVec, gp_Quaternion& theQRot)
7626   {
7627     const TCollection_AsciiString anXYZW[4] = {theArgVec[0], theArgVec[1], theArgVec[2], theArgVec[3]};
7628     if (!anXYZW[0].IsRealValue()
7629      || !anXYZW[1].IsRealValue()
7630      || !anXYZW[2].IsRealValue()
7631      || !anXYZW[3].IsRealValue())
7632     {
7633       return Standard_False;
7634     }
7635
7636     theQRot.Set (anXYZW[0].RealValue(), anXYZW[1].RealValue(), anXYZW[2].RealValue(), anXYZW[3].RealValue());
7637     return Standard_True;
7638   }
7639
7640   //! Auxiliary class for flipping image upside-down.
7641   class ImageFlipper
7642   {
7643   public:
7644
7645     //! Empty constructor.
7646     ImageFlipper() : myTmp (NCollection_BaseAllocator::CommonBaseAllocator()) {}
7647
7648     //! Perform flipping.
7649     Standard_Boolean FlipY (Image_PixMap& theImage)
7650     {
7651       if (theImage.IsEmpty()
7652        || theImage.SizeX() == 0
7653        || theImage.SizeY() == 0)
7654       {
7655         return Standard_False;
7656       }
7657
7658       const Standard_Size aRowSize = theImage.SizeRowBytes();
7659       if (myTmp.Size() < aRowSize
7660       && !myTmp.Allocate (aRowSize))
7661       {
7662         return Standard_False;
7663       }
7664
7665       // for odd height middle row should be left as is
7666       Standard_Size aNbRowsHalf = theImage.SizeY() / 2;
7667       for (Standard_Size aRowT = 0, aRowB = theImage.SizeY() - 1; aRowT < aNbRowsHalf; ++aRowT, --aRowB)
7668       {
7669         Standard_Byte* aTop = theImage.ChangeRow (aRowT);
7670         Standard_Byte* aBot = theImage.ChangeRow (aRowB);
7671         memcpy (myTmp.ChangeData(), aTop,         aRowSize);
7672         memcpy (aTop,               aBot,         aRowSize);
7673         memcpy (aBot,               myTmp.Data(), aRowSize);
7674       }
7675       return Standard_True;
7676     }
7677
7678   private:
7679     NCollection_Buffer myTmp;
7680   };
7681
7682 }
7683
7684 //=================================================================================================
7685 //function : VViewParams
7686 //purpose  : Gets or sets AIS View characteristics
7687 //=================================================================================================
7688 static int VViewParams (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7689 {
7690   Handle(V3d_View) aView = ViewerTest::CurrentView();
7691   if (aView.IsNull())
7692   {
7693     std::cout << theArgVec[0] << ": please initialize or activate view.\n";
7694     return 1;
7695   }
7696
7697   Standard_Boolean toSetProj     = Standard_False;
7698   Standard_Boolean toSetUp       = Standard_False;
7699   Standard_Boolean toSetAt       = Standard_False;
7700   Standard_Boolean toSetEye      = Standard_False;
7701   Standard_Boolean toSetScale    = Standard_False;
7702   Standard_Boolean toSetSize     = Standard_False;
7703   Standard_Boolean toSetCenter2d = Standard_False;
7704   Standard_Real    aViewScale = aView->Scale();
7705   Standard_Real    aViewSize  = 1.0;
7706   Graphic3d_Vec2i  aCenter2d;
7707   gp_XYZ aViewProj, aViewUp, aViewAt, aViewEye;
7708   aView->Proj (aViewProj.ChangeCoord (1), aViewProj.ChangeCoord (2), aViewProj.ChangeCoord (3));
7709   aView->Up   (aViewUp  .ChangeCoord (1), aViewUp  .ChangeCoord (2), aViewUp  .ChangeCoord (3));
7710   aView->At   (aViewAt  .ChangeCoord (1), aViewAt  .ChangeCoord (2), aViewAt  .ChangeCoord (3));
7711   aView->Eye  (aViewEye .ChangeCoord (1), aViewEye .ChangeCoord (2), aViewEye .ChangeCoord (3));
7712   if (theArgsNb == 1)
7713   {
7714     // print all of the available view parameters
7715     char aText[4096];
7716     Sprintf (aText,
7717              "Scale: %g\n"
7718              "Proj:  %12g %12g %12g\n"
7719              "Up:    %12g %12g %12g\n"
7720              "At:    %12g %12g %12g\n"
7721              "Eye:   %12g %12g %12g\n",
7722               aViewScale,
7723               aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7724               aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7725               aViewAt.X(),   aViewAt.Y(),   aViewAt.Z(),
7726               aViewEye.X(),  aViewEye.Y(),  aViewEye.Z());
7727     theDi << aText;
7728     return 0;
7729   }
7730
7731   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
7732   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
7733   {
7734     TCollection_AsciiString anArg (theArgVec[anArgIter]);
7735     anArg.LowerCase();
7736     if (anUpdateTool.parseRedrawMode (anArg))
7737     {
7738       continue;
7739     }
7740     else if (anArg == "-cmd"
7741           || anArg == "-command"
7742           || anArg == "-args")
7743     {
7744       char aText[4096];
7745       Sprintf (aText,
7746                "-scale %g "
7747                "-proj %g %g %g "
7748                "-up %g %g %g "
7749                "-at %g %g %g\n",
7750                 aViewScale,
7751                 aViewProj.X(), aViewProj.Y(), aViewProj.Z(),
7752                 aViewUp.X(),   aViewUp.Y(),   aViewUp.Z(),
7753                 aViewAt.X(),   aViewAt.Y(),   aViewAt.Z());
7754       theDi << aText;
7755     }
7756     else if (anArg == "-scale"
7757           || anArg == "-size")
7758     {
7759       if (anArgIter + 1 < theArgsNb
7760        && *theArgVec[anArgIter + 1] != '-')
7761       {
7762         const TCollection_AsciiString aValueArg (theArgVec[anArgIter + 1]);
7763         if (aValueArg.IsRealValue())
7764         {
7765           ++anArgIter;
7766           if (anArg == "-scale")
7767           {
7768             toSetScale = Standard_True;
7769             aViewScale = aValueArg.RealValue();
7770           }
7771           else if (anArg == "-size")
7772           {
7773             toSetSize = Standard_True;
7774             aViewSize = aValueArg.RealValue();
7775           }
7776           continue;
7777         }
7778       }
7779       if (anArg == "-scale")
7780       {
7781         theDi << "Scale: " << aView->Scale() << "\n";
7782       }
7783       else if (anArg == "-size")
7784       {
7785         Graphic3d_Vec2d aSizeXY;
7786         aView->Size (aSizeXY.x(), aSizeXY.y());
7787         theDi << "Size: " << aSizeXY.x() << " " << aSizeXY.y() << "\n";
7788       }
7789     }
7790     else if (anArg == "-eye"
7791           || anArg == "-at"
7792           || anArg == "-up"
7793           || anArg == "-proj")
7794     {
7795       if (anArgIter + 3 < theArgsNb)
7796       {
7797         gp_XYZ anXYZ;
7798         if (parseXYZ (theArgVec + anArgIter + 1, anXYZ))
7799         {
7800           anArgIter += 3;
7801           if (anArg == "-eye")
7802           {
7803             toSetEye = Standard_True;
7804             aViewEye = anXYZ;
7805           }
7806           else if (anArg == "-at")
7807           {
7808             toSetAt = Standard_True;
7809             aViewAt = anXYZ;
7810           }
7811           else if (anArg == "-up")
7812           {
7813             toSetUp = Standard_True;
7814             aViewUp = anXYZ;
7815           }
7816           else if (anArg == "-proj")
7817           {
7818             toSetProj = Standard_True;
7819             aViewProj = anXYZ;
7820           }
7821           continue;
7822         }
7823       }
7824
7825       if (anArg == "-eye")
7826       {
7827         theDi << "Eye:  " << aViewEye.X() << " " << aViewEye.Y() << " " << aViewEye.Z() << "\n";
7828       }
7829       else if (anArg == "-at")
7830       {
7831         theDi << "At:   " << aViewAt.X() << " " << aViewAt.Y() << " " << aViewAt.Z() << "\n";
7832       }
7833       else if (anArg == "-up")
7834       {
7835         theDi << "Up:   " << aViewUp.X() << " " << aViewUp.Y() << " " << aViewUp.Z() << "\n";
7836       }
7837       else if (anArg == "-proj")
7838       {
7839         theDi << "Proj: " << aViewProj.X() << " " << aViewProj.Y() << " " << aViewProj.Z() << "\n";
7840       }
7841     }
7842     else if (anArg == "-center")
7843     {
7844       if (anArgIter + 2 < theArgsNb)
7845       {
7846         const TCollection_AsciiString anX (theArgVec[anArgIter + 1]);
7847         const TCollection_AsciiString anY (theArgVec[anArgIter + 2]);
7848         if (anX.IsIntegerValue()
7849          && anY.IsIntegerValue())
7850         {
7851           toSetCenter2d = Standard_True;
7852           aCenter2d = Graphic3d_Vec2i (anX.IntegerValue(), anY.IntegerValue());
7853         }
7854       }
7855     }
7856     else
7857     {
7858       std::cout << "Syntax error at '" << anArg << "'\n";
7859       return 1;
7860     }
7861   }
7862
7863   // change view parameters in proper order
7864   if (toSetScale)
7865   {
7866     aView->SetScale (aViewScale);
7867   }
7868   if (toSetSize)
7869   {
7870     aView->SetSize (aViewSize);
7871   }
7872   if (toSetEye)
7873   {
7874     aView->SetEye (aViewEye.X(), aViewEye.Y(), aViewEye.Z());
7875   }
7876   if (toSetAt)
7877   {
7878     aView->SetAt (aViewAt.X(), aViewAt.Y(), aViewAt.Z());
7879   }
7880   if (toSetProj)
7881   {
7882     aView->SetProj (aViewProj.X(), aViewProj.Y(), aViewProj.Z());
7883   }
7884   if (toSetUp)
7885   {
7886     aView->SetUp (aViewUp.X(), aViewUp.Y(), aViewUp.Z());
7887   }
7888   if (toSetCenter2d)
7889   {
7890     aView->SetCenter (aCenter2d.x(), aCenter2d.y());
7891   }
7892
7893   return 0;
7894 }
7895
7896 //==============================================================================
7897 //function : V2DMode
7898 //purpose  :
7899 //==============================================================================
7900 static Standard_Integer V2DMode (Draw_Interpretor&, Standard_Integer theArgsNb, const char** theArgVec)
7901 {
7902   bool is2dMode = true;
7903   Handle(ViewerTest_V3dView) aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest::CurrentView());
7904   if (aV3dView.IsNull())
7905   {
7906     std::cout << "Error: no active view.\n";
7907     return 1;
7908   }
7909   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
7910   {
7911     const TCollection_AsciiString anArg = theArgVec[anArgIt];
7912     TCollection_AsciiString anArgCase = anArg;
7913     anArgCase.LowerCase();
7914     if (anArgIt + 1 < theArgsNb
7915      && anArgCase == "-name")
7916     {
7917       ViewerTest_Names aViewNames (theArgVec[++anArgIt]);
7918       TCollection_AsciiString aViewName = aViewNames.GetViewName();
7919       if (!ViewerTest_myViews.IsBound1 (aViewName))
7920       {
7921         std::cout << "Syntax error: unknown view '" << theArgVec[anArgIt - 1] << "'.\n";
7922         return 1;
7923       }
7924       aV3dView = Handle(ViewerTest_V3dView)::DownCast (ViewerTest_myViews.Find1 (aViewName));
7925     }
7926     else if (anArgCase == "-mode")
7927     {
7928       if (anArgIt + 1 < theArgsNb
7929        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], is2dMode))
7930       {
7931         ++anArgIt;
7932       }
7933     }
7934     else if (ViewerTest::ParseOnOff (theArgVec[anArgIt], is2dMode))
7935     {
7936       //
7937     }
7938     else
7939     {
7940       std::cout << "Syntax error: unknown argument " << anArg << ".\n";
7941       return 1;
7942     }
7943   }
7944
7945   aV3dView->SetView2DMode (is2dMode);
7946   return 0;
7947 }
7948
7949 //==============================================================================
7950 //function : VAnimation
7951 //purpose  :
7952 //==============================================================================
7953 static Standard_Integer VAnimation (Draw_Interpretor& theDI,
7954                                     Standard_Integer  theArgNb,
7955                                     const char**      theArgVec)
7956 {
7957   Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
7958   if (theArgNb < 2)
7959   {
7960     for (NCollection_DataMap<TCollection_AsciiString, Handle(AIS_Animation)>::Iterator
7961          anAnimIter (ViewerTest_AnimationTimelineMap); anAnimIter.More(); anAnimIter.Next())
7962     {
7963       theDI << anAnimIter.Key() << " " << anAnimIter.Value()->Duration() << " sec\n";
7964     }
7965     return 0;
7966   }
7967   if (aCtx.IsNull())
7968   {
7969     std::cout << "Error: no active view\n";
7970     return 1;
7971   }
7972
7973   Standard_Integer anArgIter = 1;
7974   TCollection_AsciiString aNameArg (theArgVec[anArgIter++]);
7975   if (aNameArg.IsEmpty())
7976   {
7977     std::cout << "Syntax error: animation name is not defined.\n";
7978     return 1;
7979   }
7980
7981   TCollection_AsciiString aNameArgLower = aNameArg;
7982   aNameArgLower.LowerCase();
7983   if (aNameArgLower == "-reset"
7984    || aNameArgLower == "-clear")
7985   {
7986     ViewerTest_AnimationTimelineMap.Clear();
7987     return 0;
7988   }
7989   else if (aNameArg.Value (1) == '-')
7990   {
7991     std::cout << "Syntax error: invalid animation name '" << aNameArg  << "'.\n";
7992     return 1;
7993   }
7994
7995   const char* aNameSplitter = "/";
7996   Standard_Integer aSplitPos = aNameArg.Search (aNameSplitter);
7997   if (aSplitPos == -1)
7998   {
7999     aNameSplitter = ".";
8000     aSplitPos = aNameArg.Search (aNameSplitter);
8001   }
8002
8003   // find existing or create a new animation by specified name within syntax "parent.child".
8004   Handle(AIS_Animation) aRootAnimation, aParentAnimation, anAnimation;
8005   for (; !aNameArg.IsEmpty();)
8006   {
8007     TCollection_AsciiString aNameParent;
8008     if (aSplitPos != -1)
8009     {
8010       if (aSplitPos == aNameArg.Length())
8011       {
8012         std::cout << "Syntax error: animation name is not defined.\n";
8013         return 1;
8014       }
8015
8016       aNameParent = aNameArg.SubString (            1, aSplitPos - 1);
8017       aNameArg    = aNameArg.SubString (aSplitPos + 1, aNameArg.Length());
8018
8019       aSplitPos = aNameArg.Search (aNameSplitter);
8020     }
8021     else
8022     {
8023       aNameParent = aNameArg;
8024       aNameArg.Clear();
8025     }
8026
8027     if (anAnimation.IsNull())
8028     {
8029       if (!ViewerTest_AnimationTimelineMap.Find (aNameParent, anAnimation))
8030       {
8031         anAnimation = new AIS_Animation (aNameParent);
8032         ViewerTest_AnimationTimelineMap.Bind (aNameParent, anAnimation);
8033       }
8034       aRootAnimation = anAnimation;
8035     }
8036     else
8037     {
8038       aParentAnimation = anAnimation;
8039       anAnimation = aParentAnimation->Find (aNameParent);
8040       if (anAnimation.IsNull())
8041       {
8042         anAnimation = new AIS_Animation (aNameParent);
8043         aParentAnimation->Add (anAnimation);
8044       }
8045     }
8046   }
8047
8048   if (anArgIter >= theArgNb)
8049   {
8050     // just print the list of children
8051     for (NCollection_Sequence<Handle(AIS_Animation)>::Iterator anAnimIter (anAnimation->Children()); anAnimIter.More(); anAnimIter.Next())
8052     {
8053       theDI << anAnimIter.Value()->Name() << " " << anAnimIter.Value()->Duration() << " sec\n";
8054     }
8055     return 0;
8056   }
8057
8058   // animation parameters
8059   Standard_Boolean toPlay = Standard_False;
8060   Standard_Real aPlaySpeed     = 1.0;
8061   Standard_Real aPlayStartTime = anAnimation->StartPts();
8062   Standard_Real aPlayDuration  = anAnimation->Duration();
8063   Standard_Boolean isFreeCamera = Standard_False;
8064   Standard_Boolean isLockLoop   = Standard_False;
8065
8066   // video recording parameters
8067   TCollection_AsciiString aRecFile;
8068   Image_VideoParams aRecParams;
8069
8070   Handle(V3d_View) aView = ViewerTest::CurrentView();
8071   for (; anArgIter < theArgNb; ++anArgIter)
8072   {
8073     TCollection_AsciiString anArg (theArgVec[anArgIter]);
8074     anArg.LowerCase();
8075     // general options
8076     if (anArg == "-reset"
8077      || anArg == "-clear")
8078     {
8079       anAnimation->Clear();
8080     }
8081     else if (anArg == "-remove"
8082           || anArg == "-del"
8083           || anArg == "-delete")
8084     {
8085       if (!aParentAnimation.IsNull())
8086       {
8087         ViewerTest_AnimationTimelineMap.UnBind (anAnimation->Name());
8088       }
8089       else
8090       {
8091         aParentAnimation->Remove (anAnimation);
8092       }
8093     }
8094     // playback options
8095     else if (anArg == "-play")
8096     {
8097       toPlay = Standard_True;
8098       if (++anArgIter < theArgNb)
8099       {
8100         if (*theArgVec[anArgIter] == '-')
8101         {
8102           --anArgIter;
8103           continue;
8104         }
8105         aPlayStartTime = Draw::Atof (theArgVec[anArgIter]);
8106
8107         if (++anArgIter < theArgNb)
8108         {
8109           if (*theArgVec[anArgIter] == '-')
8110           {
8111             --anArgIter;
8112             continue;
8113           }
8114           aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8115         }
8116       }
8117     }
8118     else if (anArg == "-resume")
8119     {
8120       toPlay = Standard_True;
8121       aPlayStartTime = anAnimation->ElapsedTime();
8122       if (++anArgIter < theArgNb)
8123       {
8124         if (*theArgVec[anArgIter] == '-')
8125         {
8126           --anArgIter;
8127           continue;
8128         }
8129
8130         aPlayDuration = Draw::Atof (theArgVec[anArgIter]);
8131       }
8132     }
8133     else if (anArg == "-playspeed"
8134           || anArg == "-speed")
8135     {
8136       if (++anArgIter >= theArgNb)
8137       {
8138         std::cout << "Syntax error at " << anArg << ".\n";
8139         return 1;
8140       }
8141       aPlaySpeed = Draw::Atof (theArgVec[anArgIter]);
8142     }
8143     else if (anArg == "-lock"
8144           || anArg == "-lockloop"
8145           || anArg == "-playlockloop")
8146     {
8147       isLockLoop = Standard_True;
8148     }
8149     else if (anArg == "-freecamera"
8150           || anArg == "-playfreecamera"
8151           || anArg == "-freelook")
8152     {
8153       isFreeCamera = Standard_True;
8154     }
8155     // video recodring options
8156     else if (anArg == "-rec"
8157           || anArg == "-record")
8158     {
8159       if (++anArgIter >= theArgNb)
8160       {
8161         std::cout << "Syntax error at " << anArg << ".\n";
8162         return 1;
8163       }
8164
8165       aRecFile = theArgVec[anArgIter];
8166       if (aRecParams.FpsNum <= 0)
8167       {
8168         aRecParams.FpsNum = 24;
8169       }
8170
8171       if (anArgIter + 2 < theArgNb
8172       && *theArgVec[anArgIter + 1] != '-'
8173       && *theArgVec[anArgIter + 2] != '-')
8174       {
8175         TCollection_AsciiString aWidthArg  (theArgVec[anArgIter + 1]);
8176         TCollection_AsciiString aHeightArg (theArgVec[anArgIter + 2]);
8177         if (aWidthArg .IsIntegerValue()
8178          && aHeightArg.IsIntegerValue())
8179         {
8180           aRecParams.Width  = aWidthArg .IntegerValue();
8181           aRecParams.Height = aHeightArg.IntegerValue();
8182           anArgIter += 2;
8183         }
8184       }
8185     }
8186     else if (anArg == "-fps")
8187     {
8188       if (++anArgIter >= theArgNb)
8189       {
8190         std::cout << "Syntax error at " << anArg << ".\n";
8191         return 1;
8192       }
8193
8194       TCollection_AsciiString aFpsArg (theArgVec[anArgIter]);
8195       Standard_Integer aSplitIndex = aFpsArg.FirstLocationInSet ("/", 1, aFpsArg.Length());
8196       if (aSplitIndex == 0)
8197       {
8198         aRecParams.FpsNum = aFpsArg.IntegerValue();
8199       }
8200       else
8201       {
8202         const TCollection_AsciiString aDenStr = aFpsArg.Split (aSplitIndex);
8203         aFpsArg.Split (aFpsArg.Length() - 1);
8204         const TCollection_AsciiString aNumStr = aFpsArg;
8205         aRecParams.FpsNum = aNumStr.IntegerValue();
8206         aRecParams.FpsDen = aDenStr.IntegerValue();
8207         if (aRecParams.FpsDen < 1)
8208         {
8209           std::cout << "Syntax error at " << anArg << ".\n";
8210           return 1;
8211         }
8212       }
8213     }
8214     else if (anArg == "-format")
8215     {
8216       if (++anArgIter >= theArgNb)
8217       {
8218         std::cout << "Syntax error at " << anArg << ".\n";
8219         return 1;
8220       }
8221       aRecParams.Format = theArgVec[anArgIter];
8222     }
8223     else if (anArg == "-pix_fmt"
8224           || anArg == "-pixfmt"
8225           || anArg == "-pixelformat")
8226     {
8227       if (++anArgIter >= theArgNb)
8228       {
8229         std::cout << "Syntax error at " << anArg << ".\n";
8230         return 1;
8231       }
8232       aRecParams.PixelFormat = theArgVec[anArgIter];
8233     }
8234     else if (anArg == "-codec"
8235           || anArg == "-vcodec"
8236           || anArg == "-videocodec")
8237     {
8238       if (++anArgIter >= theArgNb)
8239       {
8240         std::cout << "Syntax error at " << anArg << ".\n";
8241         return 1;
8242       }
8243       aRecParams.VideoCodec = theArgVec[anArgIter];
8244     }
8245     else if (anArg == "-crf"
8246           || anArg == "-preset"
8247           || anArg == "-qp")
8248     {
8249       const TCollection_AsciiString aParamName = anArg.SubString (2, anArg.Length());
8250       if (++anArgIter >= theArgNb)
8251       {
8252         std::cout << "Syntax error at " << anArg << ".\n";
8253         return 1;
8254       }
8255
8256       aRecParams.VideoCodecParams.Bind (aParamName, theArgVec[anArgIter]);
8257     }
8258     // animation definition options
8259     else if (anArg == "-start"
8260           || anArg == "-starttime"
8261           || anArg == "-startpts")
8262     {
8263       if (++anArgIter >= theArgNb)
8264       {
8265         std::cout << "Syntax error at " << anArg << ".\n";
8266         return 1;
8267       }
8268
8269       anAnimation->SetStartPts (Draw::Atof (theArgVec[anArgIter]));
8270       aRootAnimation->UpdateTotalDuration();
8271     }
8272     else if (anArg == "-end"
8273           || anArg == "-endtime"
8274           || anArg == "-endpts")
8275     {
8276       if (++anArgIter >= theArgNb)
8277       {
8278         std::cout << "Syntax error at " << anArg << ".\n";
8279         return 1;
8280       }
8281
8282       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]) - anAnimation->StartPts());
8283       aRootAnimation->UpdateTotalDuration();
8284     }
8285     else if (anArg == "-dur"
8286           || anArg == "-duration")
8287     {
8288       if (++anArgIter >= theArgNb)
8289       {
8290         std::cout << "Syntax error at " << anArg << ".\n";
8291         return 1;
8292       }
8293
8294       anAnimation->SetOwnDuration (Draw::Atof (theArgVec[anArgIter]));
8295       aRootAnimation->UpdateTotalDuration();
8296     }
8297     else if (anArg == "-command"
8298           || anArg == "-cmd"
8299           || anArg == "-invoke"
8300           || anArg == "-eval"
8301           || anArg == "-proc")
8302     {
8303       if (++anArgIter >= theArgNb)
8304       {
8305         std::cout << "Syntax error at " << anArg << ".\n";
8306         return 1;
8307       }
8308
8309       Handle(ViewerTest_AnimationProc) aCmdAnimation = new ViewerTest_AnimationProc (anAnimation->Name(), &theDI, theArgVec[anArgIter]);
8310       replaceAnimation (aParentAnimation, anAnimation, aCmdAnimation);
8311     }
8312     else if (anArg == "-objecttrsf"
8313           || anArg == "-objectransformation"
8314           || anArg == "-objtransformation"
8315           || anArg == "-objtrsf"
8316           || anArg == "-object"
8317           || anArg == "-obj")
8318     {
8319       if (++anArgIter >= theArgNb)
8320       {
8321         std::cout << "Syntax error at " << anArg << ".\n";
8322         return 1;
8323       }
8324
8325       TCollection_AsciiString anObjName (theArgVec[anArgIter]);
8326       const ViewerTest_DoubleMapOfInteractiveAndName& aMapOfAIS = GetMapOfAIS();
8327       Handle(AIS_InteractiveObject) anObject;
8328       if (!aMapOfAIS.Find2 (anObjName, anObject))
8329       {
8330         std::cout << "Syntax error: wrong object name at " << anArg << "\n";
8331         return 1;
8332       }
8333
8334       gp_Trsf       aTrsfs   [2] = { anObject->LocalTransformation(), anObject->LocalTransformation() };
8335       gp_Quaternion aRotQuats[2] = { aTrsfs[0].GetRotation(),         aTrsfs[1].GetRotation() };
8336       gp_XYZ        aLocPnts [2] = { aTrsfs[0].TranslationPart(),     aTrsfs[1].TranslationPart() };
8337       Standard_Real aScales  [2] = { aTrsfs[0].ScaleFactor(),         aTrsfs[1].ScaleFactor() };
8338       Standard_Boolean isTrsfSet = Standard_False;
8339       Standard_Integer aTrsfArgIter = anArgIter + 1;
8340       for (; aTrsfArgIter < theArgNb; ++aTrsfArgIter)
8341       {
8342         TCollection_AsciiString aTrsfArg (theArgVec[aTrsfArgIter]);
8343         aTrsfArg.LowerCase();
8344         const Standard_Integer anIndex = aTrsfArg.EndsWith ("1") ? 0 : 1;
8345         if (aTrsfArg.StartsWith ("-rotation")
8346          || aTrsfArg.StartsWith ("-rot"))
8347         {
8348           isTrsfSet = Standard_True;
8349           if (aTrsfArgIter + 4 >= theArgNb
8350           || !parseQuaternion (theArgVec + aTrsfArgIter + 1, aRotQuats[anIndex]))
8351           {
8352             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8353             return 1;
8354           }
8355           aTrsfArgIter += 4;
8356         }
8357         else if (aTrsfArg.StartsWith ("-location")
8358               || aTrsfArg.StartsWith ("-loc"))
8359         {
8360           isTrsfSet = Standard_True;
8361           if (aTrsfArgIter + 3 >= theArgNb
8362           || !parseXYZ (theArgVec + aTrsfArgIter + 1, aLocPnts[anIndex]))
8363           {
8364             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8365             return 1;
8366           }
8367           aTrsfArgIter += 3;
8368         }
8369         else if (aTrsfArg.StartsWith ("-scale"))
8370         {
8371           isTrsfSet = Standard_True;
8372           if (++aTrsfArgIter >= theArgNb)
8373           {
8374             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8375             return 1;
8376           }
8377
8378           const TCollection_AsciiString aScaleStr (theArgVec[aTrsfArgIter]);
8379           if (!aScaleStr.IsRealValue())
8380           {
8381             std::cout << "Syntax error at " << aTrsfArg << ".\n";
8382             return 1;
8383           }
8384           aScales[anIndex] = aScaleStr.RealValue();
8385         }
8386         else
8387         {
8388           anArgIter = aTrsfArgIter - 1;
8389           break;
8390         }
8391       }
8392       if (!isTrsfSet)
8393       {
8394         std::cout << "Syntax error at " << anArg << ".\n";
8395         return 1;
8396       }
8397       else if (aTrsfArgIter >= theArgNb)
8398       {
8399         anArgIter = theArgNb;
8400       }
8401
8402       aTrsfs[0].SetRotation        (aRotQuats[0]);
8403       aTrsfs[1].SetRotation        (aRotQuats[1]);
8404       aTrsfs[0].SetTranslationPart (aLocPnts[0]);
8405       aTrsfs[1].SetTranslationPart (aLocPnts[1]);
8406       aTrsfs[0].SetScaleFactor     (aScales[0]);
8407       aTrsfs[1].SetScaleFactor     (aScales[1]);
8408
8409       Handle(AIS_AnimationObject) anObjAnimation = new AIS_AnimationObject (anAnimation->Name(), aCtx, anObject, aTrsfs[0], aTrsfs[1]);
8410       replaceAnimation (aParentAnimation, anAnimation, anObjAnimation);
8411     }
8412     else if (anArg == "-viewtrsf"
8413           || anArg == "-view")
8414     {
8415       Handle(AIS_AnimationCamera) aCamAnimation = Handle(AIS_AnimationCamera)::DownCast (anAnimation);
8416       if (aCamAnimation.IsNull())
8417       {
8418         aCamAnimation = new AIS_AnimationCamera (anAnimation->Name(), aView);
8419         replaceAnimation (aParentAnimation, anAnimation, aCamAnimation);
8420       }
8421
8422       Handle(Graphic3d_Camera) aCams[2] =
8423       {
8424         new Graphic3d_Camera (aCamAnimation->View()->Camera()),
8425         new Graphic3d_Camera (aCamAnimation->View()->Camera())
8426       };
8427
8428       Standard_Boolean isTrsfSet = Standard_False;
8429       Standard_Integer aViewArgIter = anArgIter + 1;
8430       for (; aViewArgIter < theArgNb; ++aViewArgIter)
8431       {
8432         TCollection_AsciiString aViewArg (theArgVec[aViewArgIter]);
8433         aViewArg.LowerCase();
8434         const Standard_Integer anIndex = aViewArg.EndsWith("1") ? 0 : 1;
8435         if (aViewArg.StartsWith ("-scale"))
8436         {
8437           isTrsfSet = Standard_True;
8438           if (++aViewArgIter >= theArgNb)
8439           {
8440             std::cout << "Syntax error at " << anArg << ".\n";
8441             return 1;
8442           }
8443
8444           const TCollection_AsciiString aScaleStr (theArgVec[aViewArgIter]);
8445           if (!aScaleStr.IsRealValue())
8446           {
8447             std::cout << "Syntax error at " << aViewArg << ".\n";
8448             return 1;
8449           }
8450           Standard_Real aScale = aScaleStr.RealValue();
8451           aScale = aCamAnimation->View()->DefaultCamera()->Scale() / aScale;
8452           aCams[anIndex]->SetScale (aScale);
8453         }
8454         else if (aViewArg.StartsWith ("-eye")
8455               || aViewArg.StartsWith ("-center")
8456               || aViewArg.StartsWith ("-at")
8457               || aViewArg.StartsWith ("-up"))
8458         {
8459           isTrsfSet = Standard_True;
8460           gp_XYZ anXYZ;
8461           if (aViewArgIter + 3 >= theArgNb
8462           || !parseXYZ (theArgVec + aViewArgIter + 1, anXYZ))
8463           {
8464             std::cout << "Syntax error at " << aViewArg << ".\n";
8465             return 1;
8466           }
8467           aViewArgIter += 3;
8468
8469           if (aViewArg.StartsWith ("-eye"))
8470           {
8471             aCams[anIndex]->SetEye (anXYZ);
8472           }
8473           else if (aViewArg.StartsWith ("-center")
8474                 || aViewArg.StartsWith ("-at"))
8475           {
8476             aCams[anIndex]->SetCenter (anXYZ);
8477           }
8478           else if (aViewArg.StartsWith ("-up"))
8479           {
8480             aCams[anIndex]->SetUp (anXYZ);
8481           }
8482         }
8483         else
8484         {
8485           anArgIter = aViewArgIter - 1;
8486           break;
8487         }
8488       }
8489       if (!isTrsfSet)
8490       {
8491         std::cout << "Syntax error at " << anArg << ".\n";
8492         return 1;
8493       }
8494       else if (aViewArgIter >= theArgNb)
8495       {
8496         anArgIter = theArgNb;
8497       }
8498
8499       aCamAnimation->SetCameraStart(aCams[0]);
8500       aCamAnimation->SetCameraEnd  (aCams[1]);
8501     }
8502     else
8503     {
8504       std::cout << "Syntax error at " << anArg << ".\n";
8505       return 1;
8506     }
8507   }
8508
8509   if (!toPlay && aRecFile.IsEmpty())
8510   {
8511     return 0;
8512   }
8513
8514   // Start animation timeline and process frame updating.
8515   TheIsAnimating = Standard_True;
8516   const Standard_Boolean wasImmediateUpdate = aView->SetImmediateUpdate (Standard_False);
8517   Handle(Graphic3d_Camera) aCameraBack = new Graphic3d_Camera (aView->Camera());
8518   anAnimation->StartTimer (aPlayStartTime, aPlaySpeed, Standard_True, aPlayDuration <= 0.0);
8519   if (isFreeCamera)
8520   {
8521     aView->Camera()->Copy (aCameraBack);
8522   }
8523
8524   const Standard_Real anUpperPts = aPlayStartTime + aPlayDuration;
8525   if (aRecParams.FpsNum <= 0)
8526   {
8527     while (!anAnimation->IsStopped())
8528     {
8529       aCameraBack->Copy (aView->Camera());
8530       const Standard_Real aPts = anAnimation->UpdateTimer();
8531       if (isFreeCamera)
8532       {
8533         aView->Camera()->Copy (aCameraBack);
8534       }
8535
8536       if (aPts >= anUpperPts)
8537       {
8538         anAnimation->Pause();
8539         break;
8540       }
8541
8542       if (aView->IsInvalidated())
8543       {
8544         aView->Redraw();
8545       }
8546       else
8547       {
8548         aView->RedrawImmediate();
8549       }
8550
8551       if (!isLockLoop)
8552       {
8553         // handle user events
8554         theDI.Eval ("after 1 set waiter 1");
8555         theDI.Eval ("vwait waiter");
8556       }
8557       if (!TheIsAnimating)
8558       {
8559         anAnimation->Pause();
8560         theDI << aPts;
8561         break;
8562       }
8563     }
8564
8565     if (aView->IsInvalidated())
8566     {
8567       aView->Redraw();
8568     }
8569     else
8570     {
8571       aView->RedrawImmediate();
8572     }
8573   }
8574   else
8575   {
8576     OSD_Timer aPerfTimer;
8577     aPerfTimer.Start();
8578
8579     Handle(Image_VideoRecorder) aRecorder;
8580     ImageFlipper aFlipper;
8581     Handle(Draw_ProgressIndicator) aProgress;
8582     if (!aRecFile.IsEmpty())
8583     {
8584       if (aRecParams.Width  <= 0
8585        || aRecParams.Height <= 0)
8586       {
8587         aView->Window()->Size (aRecParams.Width, aRecParams.Height);
8588       }
8589
8590       aRecorder = new Image_VideoRecorder();
8591       if (!aRecorder->Open (aRecFile.ToCString(), aRecParams))
8592       {
8593         std::cout << "Error: failed to open video file for recording\n";
8594         return 0;
8595       }
8596
8597       aProgress = new Draw_ProgressIndicator (theDI, 1);
8598     }
8599
8600     // Manage frame-rated animation here
8601     Standard_Real aPts = aPlayStartTime;
8602     int64_t aNbFrames = 0;
8603     Message_ProgressSentry aPSentry (aProgress, "Video recording, sec", 0, Max (1, Standard_Integer(aPlayDuration / aPlaySpeed)), 1);
8604     Standard_Integer aSecondsProgress = 0;
8605     for (; aPts <= anUpperPts && aPSentry.More();)
8606     {
8607       const Standard_Real aRecPts = aPlaySpeed * ((Standard_Real(aRecParams.FpsDen) / Standard_Real(aRecParams.FpsNum)) * Standard_Real(aNbFrames));
8608       aPts = aPlayStartTime + aRecPts;
8609       ++aNbFrames;
8610       if (!anAnimation->Update (aPts))
8611       {
8612         break;
8613       }
8614
8615       if (!aRecorder.IsNull())
8616       {
8617         V3d_ImageDumpOptions aDumpParams;
8618         aDumpParams.Width          = aRecParams.Width;
8619         aDumpParams.Height         = aRecParams.Height;
8620         aDumpParams.BufferType     = Graphic3d_BT_RGBA;
8621         aDumpParams.StereoOptions  = V3d_SDO_MONO;
8622         aDumpParams.ToAdjustAspect = Standard_True;
8623         if (!aView->ToPixMap (aRecorder->ChangeFrame(), aDumpParams))
8624         {
8625           std::cout << "Error: view dump is failed!\n";
8626           return 0;
8627         }
8628         aFlipper.FlipY (aRecorder->ChangeFrame());
8629         if (!aRecorder->PushFrame())
8630         {
8631           return 0;
8632         }
8633       }
8634       else
8635       {
8636         aView->Redraw();
8637       }
8638
8639       while (aSecondsProgress < Standard_Integer(aRecPts / aPlaySpeed))
8640       {
8641         aPSentry.Next();
8642         ++aSecondsProgress;
8643       }
8644     }
8645
8646     aPerfTimer.Stop();
8647     anAnimation->Stop();
8648     const Standard_Real aRecFps = Standard_Real(aNbFrames) / aPerfTimer.ElapsedTime();
8649     theDI << "Average FPS: " << aRecFps << "\n"
8650           << "Nb. Frames: "  << Standard_Real(aNbFrames);
8651
8652     aView->Redraw();
8653   }
8654
8655   aView->SetImmediateUpdate (wasImmediateUpdate);
8656   TheIsAnimating = Standard_False;
8657   return 0;
8658 }
8659
8660
8661 //=======================================================================
8662 //function : VChangeSelected
8663 //purpose  : Adds the shape to selection or remove one from it
8664 //=======================================================================
8665 static Standard_Integer VChangeSelected (Draw_Interpretor& di,
8666                                 Standard_Integer argc,
8667                                 const char ** argv)
8668 {
8669   if(argc != 2)
8670   {
8671     di<<"Usage : " << argv[0] << " shape \n";
8672     return 1;
8673   }
8674   //get AIS_Shape:
8675   TCollection_AsciiString aName(argv[1]);
8676   Handle(AIS_InteractiveObject) anAISObject;
8677   if (!GetMapOfAIS().Find2 (aName, anAISObject)
8678     || anAISObject.IsNull())
8679   {
8680     di<<"Use 'vdisplay' before";
8681     return 1;
8682   }
8683
8684   ViewerTest::GetAISContext()->AddOrRemoveSelected(anAISObject, Standard_True);
8685   return 0;
8686 }
8687
8688 //=======================================================================
8689 //function : VNbSelected
8690 //purpose  : Returns number of selected objects
8691 //=======================================================================
8692 static Standard_Integer VNbSelected (Draw_Interpretor& di,
8693                                 Standard_Integer argc,
8694                                 const char ** argv)
8695 {
8696   if(argc != 1)
8697   {
8698     di << "Usage : " << argv[0] << "\n";
8699     return 1;
8700   }
8701   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8702   if(aContext.IsNull())
8703   {
8704     di << "use 'vinit' command before " << argv[0] << "\n";
8705     return 1;
8706   }
8707   di << aContext->NbSelected() << "\n";
8708   return 0;
8709 }
8710
8711 //=======================================================================
8712 //function : VPurgeDisplay
8713 //purpose  : Switches altialiasing on or off
8714 //=======================================================================
8715 static Standard_Integer VPurgeDisplay (Draw_Interpretor& di,
8716                                 Standard_Integer argc,
8717                                 const char ** argv)
8718 {
8719   if (argc > 1)
8720   {
8721     di << "Usage : " << argv[0] << "\n";
8722     return 1;
8723   }
8724   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8725   if (aContext.IsNull())
8726   {
8727     di << "use 'vinit' command before " << argv[0] << "\n";
8728     return 1;
8729   }
8730
8731   di << aContext->PurgeDisplay() << "\n";
8732   return 0;
8733 }
8734
8735 //=======================================================================
8736 //function : VSetViewSize
8737 //purpose  :
8738 //=======================================================================
8739 static Standard_Integer VSetViewSize (Draw_Interpretor& di,
8740                                 Standard_Integer argc,
8741                                 const char ** argv)
8742 {
8743   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8744   if(aContext.IsNull())
8745   {
8746     di << "use 'vinit' command before " << argv[0] << "\n";
8747     return 1;
8748   }
8749   if(argc != 2)
8750   {
8751     di<<"Usage : " << argv[0] << " Size\n";
8752     return 1;
8753   }
8754   Standard_Real aSize = Draw::Atof (argv[1]);
8755   if (aSize <= 0.)
8756   {
8757     di<<"Bad Size value  : " << aSize << "\n";
8758     return 1;
8759   }
8760
8761   Handle(V3d_View) aView = ViewerTest::CurrentView();
8762   aView->SetSize(aSize);
8763   return 0;
8764 }
8765
8766 //=======================================================================
8767 //function : VMoveView
8768 //purpose  :
8769 //=======================================================================
8770 static Standard_Integer VMoveView (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->Move(Dx,Dy,Dz,aStart);
8796   return 0;
8797 }
8798
8799 //=======================================================================
8800 //function : VTranslateView
8801 //purpose  :
8802 //=======================================================================
8803 static Standard_Integer VTranslateView (Draw_Interpretor& di,
8804                                 Standard_Integer argc,
8805                                 const char ** argv)
8806 {
8807   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8808   if(aContext.IsNull())
8809   {
8810     di << "use 'vinit' command before " << argv[0] << "\n";
8811     return 1;
8812   }
8813   if(argc < 4 || argc > 5)
8814   {
8815     di<<"Usage : " << argv[0] << " Dx Dy Dz [Start = 1|0]\n";
8816     return 1;
8817   }
8818   Standard_Real Dx = Draw::Atof (argv[1]);
8819   Standard_Real Dy = Draw::Atof (argv[2]);
8820   Standard_Real Dz = Draw::Atof (argv[3]);
8821   Standard_Boolean aStart = Standard_True;
8822   if (argc == 5)
8823   {
8824       aStart = (Draw::Atoi (argv[4]) > 0);
8825   }
8826
8827   Handle(V3d_View) aView = ViewerTest::CurrentView();
8828   aView->Translate(Dx,Dy,Dz,aStart);
8829   return 0;
8830 }
8831
8832 //=======================================================================
8833 //function : VTurnView
8834 //purpose  :
8835 //=======================================================================
8836 static Standard_Integer VTurnView (Draw_Interpretor& di,
8837                                 Standard_Integer argc,
8838                                 const char ** argv)
8839 {
8840   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
8841   if(aContext.IsNull()) {
8842     di << "use 'vinit' command before " << argv[0] << "\n";
8843     return 1;
8844   }
8845   if(argc < 4 || argc > 5){
8846     di<<"Usage : " << argv[0] << " Ax Ay Az [Start = 1|0]\n";
8847     return 1;
8848   }
8849   Standard_Real Ax = Draw::Atof (argv[1]);
8850   Standard_Real Ay = Draw::Atof (argv[2]);
8851   Standard_Real Az = Draw::Atof (argv[3]);
8852   Standard_Boolean aStart = Standard_True;
8853   if (argc == 5)
8854   {
8855       aStart = (Draw::Atoi (argv[4]) > 0);
8856   }
8857
8858   Handle(V3d_View) aView = ViewerTest::CurrentView();
8859   aView->Turn(Ax,Ay,Az,aStart);
8860   return 0;
8861 }
8862
8863 //==============================================================================
8864 //function : VTextureEnv
8865 //purpose  : ENables or disables environment mapping
8866 //==============================================================================
8867 class OCC_TextureEnv : public Graphic3d_TextureEnv
8868 {
8869 public:
8870   OCC_TextureEnv(const Standard_CString FileName);
8871   OCC_TextureEnv(const Graphic3d_NameOfTextureEnv aName);
8872   void SetTextureParameters(const Standard_Boolean theRepeatFlag,
8873                             const Standard_Boolean theModulateFlag,
8874                             const Graphic3d_TypeOfTextureFilter theFilter,
8875                             const Standard_ShortReal theXScale,
8876                             const Standard_ShortReal theYScale,
8877                             const Standard_ShortReal theXShift,
8878                             const Standard_ShortReal theYShift,
8879                             const Standard_ShortReal theAngle);
8880   DEFINE_STANDARD_RTTI_INLINE(OCC_TextureEnv,Graphic3d_TextureEnv)
8881 };
8882 DEFINE_STANDARD_HANDLE(OCC_TextureEnv, Graphic3d_TextureEnv)
8883
8884 OCC_TextureEnv::OCC_TextureEnv(const Standard_CString theFileName)
8885   : Graphic3d_TextureEnv(theFileName)
8886 {
8887 }
8888
8889 OCC_TextureEnv::OCC_TextureEnv(const Graphic3d_NameOfTextureEnv theTexId)
8890   : Graphic3d_TextureEnv(theTexId)
8891 {
8892 }
8893
8894 void OCC_TextureEnv::SetTextureParameters(const Standard_Boolean theRepeatFlag,
8895                                           const Standard_Boolean theModulateFlag,
8896                                           const Graphic3d_TypeOfTextureFilter theFilter,
8897                                           const Standard_ShortReal theXScale,
8898                                           const Standard_ShortReal theYScale,
8899                                           const Standard_ShortReal theXShift,
8900                                           const Standard_ShortReal theYShift,
8901                                           const Standard_ShortReal theAngle)
8902 {
8903   myParams->SetRepeat     (theRepeatFlag);
8904   myParams->SetModulate   (theModulateFlag);
8905   myParams->SetFilter     (theFilter);
8906   myParams->SetScale      (Graphic3d_Vec2(theXScale, theYScale));
8907   myParams->SetTranslation(Graphic3d_Vec2(theXShift, theYShift));
8908   myParams->SetRotation   (theAngle);
8909 }
8910
8911 static int VTextureEnv (Draw_Interpretor& /*theDI*/, Standard_Integer theArgNb, const char** theArgVec)
8912 {
8913   // get the active view
8914   Handle(V3d_View) aView = ViewerTest::CurrentView();
8915   if (aView.IsNull())
8916   {
8917     std::cerr << "No active view. Please call vinit.\n";
8918     return 1;
8919   }
8920
8921   // Checking the input arguments
8922   Standard_Boolean anEnableFlag = Standard_False;
8923   Standard_Boolean isOk         = theArgNb >= 2;
8924   if (isOk)
8925   {
8926     TCollection_AsciiString anEnableOpt(theArgVec[1]);
8927     anEnableFlag = anEnableOpt.IsEqual("on");
8928     isOk         = anEnableFlag || anEnableOpt.IsEqual("off");
8929   }
8930   if (anEnableFlag)
8931   {
8932     isOk = (theArgNb == 3 || theArgNb == 11);
8933     if (isOk)
8934     {
8935       TCollection_AsciiString aTextureOpt(theArgVec[2]);
8936       isOk = (!aTextureOpt.IsIntegerValue() ||
8937              (aTextureOpt.IntegerValue() >= 0 && aTextureOpt.IntegerValue() < Graphic3d_NOT_ENV_UNKNOWN));
8938
8939       if (isOk && theArgNb == 11)
8940       {
8941         TCollection_AsciiString aRepeatOpt  (theArgVec[3]),
8942                                 aModulateOpt(theArgVec[4]),
8943                                 aFilterOpt  (theArgVec[5]),
8944                                 aSScaleOpt  (theArgVec[6]),
8945                                 aTScaleOpt  (theArgVec[7]),
8946                                 aSTransOpt  (theArgVec[8]),
8947                                 aTTransOpt  (theArgVec[9]),
8948                                 anAngleOpt  (theArgVec[10]);
8949         isOk = ((aRepeatOpt.  IsEqual("repeat")   || aRepeatOpt.  IsEqual("clamp")) &&
8950                 (aModulateOpt.IsEqual("modulate") || aModulateOpt.IsEqual("decal")) &&
8951                 (aFilterOpt.  IsEqual("nearest")  || aFilterOpt.  IsEqual("bilinear") || aFilterOpt.IsEqual("trilinear")) &&
8952                 aSScaleOpt.IsRealValue() && aTScaleOpt.IsRealValue() &&
8953                 aSTransOpt.IsRealValue() && aTTransOpt.IsRealValue() &&
8954                 anAngleOpt.IsRealValue());
8955       }
8956     }
8957   }
8958
8959   if (!isOk)
8960   {
8961     std::cerr << "Usage :" << std::endl;
8962     std::cerr << theArgVec[0] << " off" << std::endl;
8963     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;
8964     return 1;
8965   }
8966
8967   if (anEnableFlag)
8968   {
8969     TCollection_AsciiString aTextureOpt(theArgVec[2]);
8970     Handle(OCC_TextureEnv) aTexEnv = aTextureOpt.IsIntegerValue() ?
8971                                      new OCC_TextureEnv((Graphic3d_NameOfTextureEnv)aTextureOpt.IntegerValue()) :
8972                                      new OCC_TextureEnv(theArgVec[2]);
8973
8974     if (theArgNb == 11)
8975     {
8976       TCollection_AsciiString aRepeatOpt(theArgVec[3]), aModulateOpt(theArgVec[4]), aFilterOpt(theArgVec[5]);
8977       aTexEnv->SetTextureParameters(
8978         aRepeatOpt.  IsEqual("repeat"),
8979         aModulateOpt.IsEqual("modulate"),
8980         aFilterOpt.  IsEqual("nearest") ? Graphic3d_TOTF_NEAREST :
8981                                           aFilterOpt.IsEqual("bilinear") ? Graphic3d_TOTF_BILINEAR :
8982                                                                            Graphic3d_TOTF_TRILINEAR,
8983         (Standard_ShortReal)Draw::Atof(theArgVec[6]),
8984         (Standard_ShortReal)Draw::Atof(theArgVec[7]),
8985         (Standard_ShortReal)Draw::Atof(theArgVec[8]),
8986         (Standard_ShortReal)Draw::Atof(theArgVec[9]),
8987         (Standard_ShortReal)Draw::Atof(theArgVec[10])
8988         );
8989     }
8990     aView->SetTextureEnv(aTexEnv);
8991   }
8992   else // Disabling environment mapping
8993   {
8994     Handle(Graphic3d_TextureEnv) aTexture;
8995     aView->SetTextureEnv(aTexture); // Passing null handle to clear the texture data
8996   }
8997
8998   aView->Redraw();
8999   return 0;
9000 }
9001
9002 namespace
9003 {
9004   typedef NCollection_DataMap<TCollection_AsciiString, Handle(Graphic3d_ClipPlane)> MapOfPlanes;
9005
9006   //! Remove registered clipping plane from all views and objects.
9007   static void removePlane (MapOfPlanes& theRegPlanes,
9008                            const TCollection_AsciiString& theName)
9009   {
9010     Handle(Graphic3d_ClipPlane) aClipPlane;
9011     if (!theRegPlanes.Find (theName, aClipPlane))
9012     {
9013       std::cout << "Warning: no such plane.\n";
9014       return;
9015     }
9016
9017     theRegPlanes.UnBind (theName);
9018     for (ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName anIObjIt (GetMapOfAIS());
9019          anIObjIt.More(); anIObjIt.Next())
9020     {
9021       const Handle(AIS_InteractiveObject)& aPrs = anIObjIt.Key1();
9022       aPrs->RemoveClipPlane (aClipPlane);
9023     }
9024
9025     for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
9026          aViewIt.More(); aViewIt.Next())
9027     {
9028       const Handle(V3d_View)& aView = aViewIt.Key2();
9029       aView->RemoveClipPlane(aClipPlane);
9030     }
9031
9032     ViewerTest::RedrawAllViews();
9033   }
9034 }
9035
9036 //===============================================================================================
9037 //function : VClipPlane
9038 //purpose  :
9039 //===============================================================================================
9040 static int VClipPlane (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9041 {
9042   // use short-cut for created clip planes map of created (or "registered by name") clip planes
9043   static MapOfPlanes aRegPlanes;
9044
9045   if (theArgsNb < 2)
9046   {
9047     for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More(); aPlaneIter.Next())
9048     {
9049       theDi << aPlaneIter.Key() << " ";
9050     }
9051     return 0;
9052   }
9053
9054   TCollection_AsciiString aCommand (theArgVec[1]);
9055   aCommand.LowerCase();
9056   const Handle(V3d_View)& anActiveView = ViewerTest::CurrentView();
9057   if (anActiveView.IsNull())
9058   {
9059     std::cout << "Error: no active view.\n";
9060     return 1;
9061   }
9062
9063   // print maximum number of planes for current viewer
9064   if (aCommand == "-maxplanes"
9065    || aCommand == "maxplanes")
9066   {
9067     theDi << anActiveView->Viewer()->Driver()->InquirePlaneLimit()
9068           << " plane slots provided by driver.\n";
9069     return 0;
9070   }
9071
9072   // create / delete plane instance
9073   if (aCommand == "-create"
9074    || aCommand == "create"
9075    || aCommand == "-delete"
9076    || aCommand == "delete"
9077    || aCommand == "-clone"
9078    || aCommand == "clone")
9079   {
9080     if (theArgsNb < 3)
9081     {
9082       std::cout << "Syntax error: plane name is required.\n";
9083       return 1;
9084     }
9085
9086     Standard_Boolean toCreate = aCommand == "-create"
9087                              || aCommand == "create";
9088     Standard_Boolean toClone  = aCommand == "-clone"
9089                              || aCommand == "clone";
9090     Standard_Boolean toDelete = aCommand == "-delete"
9091                              || aCommand == "delete";
9092     TCollection_AsciiString aPlane (theArgVec[2]);
9093
9094     if (toCreate)
9095     {
9096       if (aRegPlanes.IsBound (aPlane))
9097       {
9098         std::cout << "Warning: existing plane has been overridden.\n";
9099         toDelete = true;
9100       }
9101       else
9102       {
9103         aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9104         return 0;
9105       }
9106     }
9107     else if (toClone) // toClone
9108     {
9109       if (!aRegPlanes.IsBound (aPlane))
9110       {
9111         std::cout << "Error: no such plane.\n";
9112         return 1;
9113       }
9114       else if (theArgsNb < 4)
9115       {
9116         std::cout << "Syntax error: enter name for new plane.\n";
9117         return 1;
9118       }
9119
9120       TCollection_AsciiString aClone (theArgVec[3]);
9121       if (aRegPlanes.IsBound (aClone))
9122       {
9123         std::cout << "Error: plane name is in use.\n";
9124         return 1;
9125       }
9126
9127       const Handle(Graphic3d_ClipPlane)& aClipPlane = aRegPlanes.Find (aPlane);
9128
9129       aRegPlanes.Bind (aClone, aClipPlane->Clone());
9130       return 0;
9131     }
9132
9133     if (toDelete)
9134     {
9135       if (aPlane == "ALL"
9136        || aPlane == "all"
9137        || aPlane == "*")
9138       {
9139         for (MapOfPlanes::Iterator aPlaneIter (aRegPlanes); aPlaneIter.More();)
9140         {
9141           aPlane = aPlaneIter.Key();
9142           removePlane (aRegPlanes, aPlane);
9143           aPlaneIter = MapOfPlanes::Iterator (aRegPlanes);
9144         }
9145       }
9146       else
9147       {
9148         removePlane (aRegPlanes, aPlane);
9149       }
9150     }
9151
9152     if (toCreate)
9153     {
9154       aRegPlanes.Bind (aPlane, new Graphic3d_ClipPlane());
9155     }
9156     return 0;
9157   }
9158
9159   // set / unset plane command
9160   if (aCommand == "set"
9161    || aCommand == "unset")
9162   {
9163     if (theArgsNb < 5)
9164     {
9165       std::cout << "Syntax error: need more arguments.\n";
9166       return 1;
9167     }
9168
9169     // redirect to new syntax
9170     NCollection_Array1<const char*> anArgVec (1, theArgsNb - 1);
9171     anArgVec.SetValue (1, theArgVec[0]);
9172     anArgVec.SetValue (2, theArgVec[2]);
9173     anArgVec.SetValue (3, aCommand == "set" ? "-set" : "-unset");
9174     for (Standard_Integer anIt = 4; anIt < theArgsNb; ++anIt)
9175     {
9176       anArgVec.SetValue (anIt, theArgVec[anIt]);
9177     }
9178
9179     return VClipPlane (theDi, anArgVec.Length(), &anArgVec.ChangeFirst());
9180   }
9181
9182   // change plane command
9183   TCollection_AsciiString aPlaneName;
9184   Handle(Graphic3d_ClipPlane) aClipPlane;
9185   Standard_Integer anArgIter = 0;
9186   if (aCommand == "-change"
9187    || aCommand == "change")
9188   {
9189     // old syntax support
9190     if (theArgsNb < 3)
9191     {
9192       std::cout << "Syntax error: need more arguments.\n";
9193       return 1;
9194     }
9195
9196     anArgIter  = 3;
9197     aPlaneName = theArgVec[2];
9198     if (!aRegPlanes.Find (aPlaneName, aClipPlane))
9199     {
9200       std::cout << "Error: no such plane '" << aPlaneName << "'.\n";
9201       return 1;
9202     }
9203   }
9204   else if (aRegPlanes.Find (theArgVec[1], aClipPlane))
9205   {
9206     anArgIter  = 2;
9207     aPlaneName = theArgVec[1];
9208   }
9209   else
9210   {
9211     anArgIter  = 2;
9212     aPlaneName = theArgVec[1];
9213     aClipPlane = new Graphic3d_ClipPlane();
9214     aRegPlanes.Bind (aPlaneName, aClipPlane);
9215     theDi << "Created new plane " << aPlaneName << ".\n";
9216   }
9217
9218   if (theArgsNb - anArgIter < 1)
9219   {
9220     std::cout << "Syntax error: need more arguments.\n";
9221     return 1;
9222   }
9223
9224   for (; anArgIter < theArgsNb; ++anArgIter)
9225   {
9226     const char**     aChangeArgs   = theArgVec + anArgIter;
9227     Standard_Integer aNbChangeArgs = theArgsNb - anArgIter;
9228     TCollection_AsciiString aChangeArg (aChangeArgs[0]);
9229     aChangeArg.LowerCase();
9230
9231     Standard_Boolean toEnable = Standard_True;
9232     if (ViewerTest::ParseOnOff (aChangeArgs[0], toEnable))
9233     {
9234       aClipPlane->SetOn (toEnable);
9235     }
9236     else if (aChangeArg.StartsWith ("-equation")
9237           || aChangeArg.StartsWith ("equation"))
9238     {
9239       if (aNbChangeArgs < 5)
9240       {
9241         std::cout << "Syntax error: need more arguments.\n";
9242         return 1;
9243       }
9244
9245       Standard_Integer aSubIndex = 1;
9246       Standard_Integer aPrefixLen = 8 + (aChangeArg.Value (1) == '-' ? 1 : 0);
9247       if (aPrefixLen < aChangeArg.Length())
9248       {
9249         TCollection_AsciiString aSubStr = aChangeArg.SubString (aPrefixLen + 1, aChangeArg.Length());
9250         if (!aSubStr.IsIntegerValue()
9251           || aSubStr.IntegerValue() <= 0)
9252         {
9253           std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9254           return 1;
9255         }
9256         aSubIndex = aSubStr.IntegerValue();
9257       }
9258
9259       Standard_Real aCoeffA = Draw::Atof (aChangeArgs[1]);
9260       Standard_Real aCoeffB = Draw::Atof (aChangeArgs[2]);
9261       Standard_Real aCoeffC = Draw::Atof (aChangeArgs[3]);
9262       Standard_Real aCoeffD = Draw::Atof (aChangeArgs[4]);
9263       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9264       for (Standard_Integer aSubPlaneIter = 1; aSubPlaneIter < aSubIndex; ++aSubPlaneIter)
9265       {
9266         if (aSubPln->ChainNextPlane().IsNull())
9267         {
9268           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9269         }
9270         aSubPln = aSubPln->ChainNextPlane();
9271       }
9272       aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9273       aSubPln->SetEquation (gp_Pln (aCoeffA, aCoeffB, aCoeffC, aCoeffD));
9274       anArgIter += 4;
9275     }
9276     else if ((aChangeArg == "-boxinterior"
9277            || aChangeArg == "-boxint"
9278            || aChangeArg == "-box")
9279             && aNbChangeArgs >= 7)
9280     {
9281       Graphic3d_BndBox3d aBndBox;
9282       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[1]), Draw::Atof (aChangeArgs[2]), Draw::Atof (aChangeArgs[3])));
9283       aBndBox.Add (Graphic3d_Vec3d (Draw::Atof (aChangeArgs[4]), Draw::Atof (aChangeArgs[5]), Draw::Atof (aChangeArgs[6])));
9284       anArgIter += 6;
9285
9286       Standard_Integer aNbSubPlanes = 6;
9287       const Graphic3d_Vec3d aDirArray[6] =
9288       {
9289         Graphic3d_Vec3d (-1, 0, 0),
9290         Graphic3d_Vec3d ( 1, 0, 0),
9291         Graphic3d_Vec3d ( 0,-1, 0),
9292         Graphic3d_Vec3d ( 0, 1, 0),
9293         Graphic3d_Vec3d ( 0, 0,-1),
9294         Graphic3d_Vec3d ( 0, 0, 1),
9295       };
9296       Handle(Graphic3d_ClipPlane) aSubPln = aClipPlane;
9297       for (Standard_Integer aSubPlaneIter = 0; aSubPlaneIter < aNbSubPlanes; ++aSubPlaneIter)
9298       {
9299         const Graphic3d_Vec3d& aDir = aDirArray[aSubPlaneIter];
9300         const Standard_Real aW = -aDir.Dot ((aSubPlaneIter % 2 == 1) ? aBndBox.CornerMax() : aBndBox.CornerMin());
9301         aSubPln->SetEquation (gp_Pln (aDir.x(), aDir.y(), aDir.z(), aW));
9302         if (aSubPlaneIter + 1 == aNbSubPlanes)
9303         {
9304           aSubPln->SetChainNextPlane (Handle(Graphic3d_ClipPlane)());
9305         }
9306         else
9307         {
9308           aSubPln->SetChainNextPlane (new Graphic3d_ClipPlane (*aSubPln));
9309         }
9310         aSubPln = aSubPln->ChainNextPlane();
9311       }
9312     }
9313     else if (aChangeArg == "-capping"
9314           || aChangeArg == "capping")
9315     {
9316       if (aNbChangeArgs < 2)
9317       {
9318         std::cout << "Syntax error: need more arguments.\n";
9319         return 1;
9320       }
9321
9322       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9323       {
9324         aClipPlane->SetCapping (toEnable);
9325         anArgIter += 1;
9326       }
9327       else
9328       {
9329         // just skip otherwise (old syntax)
9330       }
9331     }
9332     else if (aChangeArg == "-useobjectmaterial"
9333           || aChangeArg == "-useobjectmat"
9334           || aChangeArg == "-useobjmat"
9335           || aChangeArg == "-useobjmaterial")
9336     {
9337       if (aNbChangeArgs < 2)
9338       {
9339         std::cout << "Syntax error: need more arguments.\n";
9340         return 1;
9341       }
9342
9343       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9344       {
9345         aClipPlane->SetUseObjectMaterial (toEnable == Standard_True);
9346         anArgIter += 1;
9347       }
9348     }
9349     else if (aChangeArg == "-useobjecttexture"
9350           || aChangeArg == "-useobjecttex"
9351           || aChangeArg == "-useobjtexture"
9352           || aChangeArg == "-useobjtex")
9353     {
9354       if (aNbChangeArgs < 2)
9355       {
9356         std::cout << "Syntax error: need more arguments.\n";
9357         return 1;
9358       }
9359
9360       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9361       {
9362         aClipPlane->SetUseObjectTexture (toEnable == Standard_True);
9363         anArgIter += 1;
9364       }
9365     }
9366     else if (aChangeArg == "-useobjectshader"
9367           || aChangeArg == "-useobjshader")
9368     {
9369       if (aNbChangeArgs < 2)
9370       {
9371         std::cout << "Syntax error: need more arguments.\n";
9372         return 1;
9373       }
9374
9375       if (ViewerTest::ParseOnOff (aChangeArgs[1], toEnable))
9376       {
9377         aClipPlane->SetUseObjectShader (toEnable == Standard_True);
9378         anArgIter += 1;
9379       }
9380     }
9381     else if (aChangeArg == "-color"
9382           || aChangeArg == "color")
9383     {
9384       Quantity_Color aColor;
9385       Standard_Integer aNbParsed = ViewerTest::ParseColor (aNbChangeArgs - 1,
9386                                                            aChangeArgs + 1,
9387                                                            aColor);
9388       if (aNbParsed == 0)
9389       {
9390         std::cout << "Syntax error: need more arguments.\n";
9391         return 1;
9392       }
9393
9394       Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9395       aMat.SetAmbientColor (aColor);
9396       aMat.SetDiffuseColor (aColor);
9397       aClipPlane->SetCappingMaterial (aMat);
9398       anArgIter += aNbParsed;
9399     }
9400     else if ((aChangeArg == "-transparency"
9401            || aChangeArg == "-transp")
9402           && aNbChangeArgs >= 2)
9403     {
9404       TCollection_AsciiString aValStr (aChangeArgs[1]);
9405       Handle(Graphic3d_AspectFillArea3d) anAspect = aClipPlane->CappingAspect();
9406       if (aValStr.IsRealValue())
9407       {
9408         Graphic3d_MaterialAspect aMat = aClipPlane->CappingMaterial();
9409         aMat.SetTransparency ((float )aValStr.RealValue());
9410         anAspect->SetAlphaMode (Graphic3d_AlphaMode_BlendAuto);
9411         aClipPlane->SetCappingMaterial (aMat);
9412       }
9413       else
9414       {
9415         aValStr.LowerCase();
9416         Graphic3d_AlphaMode aMode = Graphic3d_AlphaMode_BlendAuto;
9417         if (aValStr == "opaque")
9418         {
9419           aMode = Graphic3d_AlphaMode_Opaque;
9420         }
9421         else if (aValStr == "mask")
9422         {
9423           aMode = Graphic3d_AlphaMode_Mask;
9424         }
9425         else if (aValStr == "blend")
9426         {
9427           aMode = Graphic3d_AlphaMode_Blend;
9428         }
9429         else if (aValStr == "blendauto")
9430         {
9431           aMode = Graphic3d_AlphaMode_BlendAuto;
9432         }
9433         else
9434         {
9435           std::cout << "Syntax error at '" << aValStr << "'\n";
9436           return 1;
9437         }
9438         anAspect->SetAlphaMode (aMode);
9439         aClipPlane->SetCappingAspect (anAspect);
9440       }
9441       anArgIter += 1;
9442     }
9443     else if (aChangeArg == "-texname"
9444           || aChangeArg == "texname")
9445     {
9446       if (aNbChangeArgs < 2)
9447       {
9448         std::cout << "Syntax error: need more arguments.\n";
9449         return 1;
9450       }
9451
9452       TCollection_AsciiString aTextureName (aChangeArgs[1]);
9453       Handle(Graphic3d_Texture2Dmanual) aTexture = new Graphic3d_Texture2Dmanual(aTextureName);
9454       if (!aTexture->IsDone())
9455       {
9456         aClipPlane->SetCappingTexture (NULL);
9457       }
9458       else
9459       {
9460         aTexture->EnableModulate();
9461         aTexture->EnableRepeat();
9462         aClipPlane->SetCappingTexture (aTexture);
9463       }
9464       anArgIter += 1;
9465     }
9466     else if (aChangeArg == "-texscale"
9467           || aChangeArg == "texscale")
9468     {
9469       if (aClipPlane->CappingTexture().IsNull())
9470       {
9471         std::cout << "Error: no texture is set.\n";
9472         return 1;
9473       }
9474
9475       if (aNbChangeArgs < 3)
9476       {
9477         std::cout << "Syntax error: need more arguments.\n";
9478         return 1;
9479       }
9480
9481       Standard_ShortReal aSx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9482       Standard_ShortReal aSy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9483       aClipPlane->CappingTexture()->GetParams()->SetScale (Graphic3d_Vec2 (aSx, aSy));
9484       anArgIter += 2;
9485     }
9486     else if (aChangeArg == "-texorigin"
9487           || aChangeArg == "texorigin") // texture origin
9488     {
9489       if (aClipPlane->CappingTexture().IsNull())
9490       {
9491         std::cout << "Error: no texture is set.\n";
9492         return 1;
9493       }
9494
9495       if (aNbChangeArgs < 3)
9496       {
9497         std::cout << "Syntax error: need more arguments.\n";
9498         return 1;
9499       }
9500
9501       Standard_ShortReal aTx = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9502       Standard_ShortReal aTy = (Standard_ShortReal)Draw::Atof (aChangeArgs[2]);
9503
9504       aClipPlane->CappingTexture()->GetParams()->SetTranslation (Graphic3d_Vec2 (aTx, aTy));
9505       anArgIter += 2;
9506     }
9507     else if (aChangeArg == "-texrotate"
9508           || aChangeArg == "texrotate") // texture rotation
9509     {
9510       if (aClipPlane->CappingTexture().IsNull())
9511       {
9512         std::cout << "Error: no texture is set.\n";
9513         return 1;
9514       }
9515
9516       if (aNbChangeArgs < 2)
9517       {
9518         std::cout << "Syntax error: need more arguments.\n";
9519         return 1;
9520       }
9521
9522       Standard_ShortReal aRot = (Standard_ShortReal)Draw::Atof (aChangeArgs[1]);
9523       aClipPlane->CappingTexture()->GetParams()->SetRotation (aRot);
9524       anArgIter += 1;
9525     }
9526     else if (aChangeArg == "-hatch"
9527           || aChangeArg == "hatch")
9528     {
9529       if (aNbChangeArgs < 2)
9530       {
9531         std::cout << "Syntax error: need more arguments.\n";
9532         return 1;
9533       }
9534
9535       TCollection_AsciiString aHatchStr (aChangeArgs[1]);
9536       aHatchStr.LowerCase();
9537       if (aHatchStr == "on")
9538       {
9539         aClipPlane->SetCappingHatchOn();
9540       }
9541       else if (aHatchStr == "off")
9542       {
9543         aClipPlane->SetCappingHatchOff();
9544       }
9545       else
9546       {
9547         aClipPlane->SetCappingHatch ((Aspect_HatchStyle)Draw::Atoi (aChangeArgs[1]));
9548       }
9549       anArgIter += 1;
9550     }
9551     else if (aChangeArg == "-delete"
9552           || aChangeArg == "delete")
9553     {
9554       removePlane (aRegPlanes, aPlaneName);
9555       return 0;
9556     }
9557     else if (aChangeArg == "-set"
9558           || aChangeArg == "-unset"
9559           || aChangeArg == "-setoverrideglobal")
9560     {
9561       // set / unset plane command
9562       const Standard_Boolean toSet            = aChangeArg.StartsWith ("-set");
9563       const Standard_Boolean toOverrideGlobal = aChangeArg == "-setoverrideglobal";
9564       Standard_Integer anIt = 1;
9565       for (; anIt < aNbChangeArgs; ++anIt)
9566       {
9567         TCollection_AsciiString anEntityName (aChangeArgs[anIt]);
9568         if (anEntityName.IsEmpty()
9569          || anEntityName.Value (1) == '-')
9570         {
9571           break;
9572         }
9573         else if (!toOverrideGlobal
9574                && ViewerTest_myViews.IsBound1 (anEntityName))
9575         {
9576           Handle(V3d_View) aView = ViewerTest_myViews.Find1 (anEntityName);
9577           if (toSet)
9578           {
9579             aView->AddClipPlane (aClipPlane);
9580           }
9581           else
9582           {
9583             aView->RemoveClipPlane (aClipPlane);
9584           }
9585           continue;
9586         }
9587         else if (GetMapOfAIS().IsBound2 (anEntityName))
9588         {
9589           Handle(AIS_InteractiveObject) aIObj = GetMapOfAIS().Find2 (anEntityName);
9590           if (toSet)
9591           {
9592             aIObj->AddClipPlane (aClipPlane);
9593           }
9594           else
9595           {
9596             aIObj->RemoveClipPlane (aClipPlane);
9597           }
9598           if (!aIObj->ClipPlanes().IsNull())
9599           {
9600             aIObj->ClipPlanes()->SetOverrideGlobal (toOverrideGlobal);
9601           }
9602         }
9603         else
9604         {
9605           std::cout << "Error: object/view '" << anEntityName << "' is not found!\n";
9606           return 1;
9607         }
9608       }
9609
9610       if (anIt == 1)
9611       {
9612         // apply to active view
9613         if (toSet)
9614         {
9615           anActiveView->AddClipPlane (aClipPlane);
9616         }
9617         else
9618         {
9619           anActiveView->RemoveClipPlane (aClipPlane);
9620         }
9621       }
9622       else
9623       {
9624         anArgIter = anArgIter + anIt - 1;
9625       }
9626     }
9627     else
9628     {
9629       std::cout << "Syntax error: unknown argument '" << aChangeArg << "'.\n";
9630       return 1;
9631     }
9632   }
9633
9634   ViewerTest::RedrawAllViews();
9635   return 0;
9636 }
9637
9638 //===============================================================================================
9639 //function : VZRange
9640 //purpose  :
9641 //===============================================================================================
9642 static int VZRange (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9643 {
9644   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9645
9646   if (aCurrentView.IsNull())
9647   {
9648     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9649     return 1;
9650   }
9651
9652   Handle(Graphic3d_Camera) aCamera = aCurrentView->Camera();
9653
9654   if (theArgsNb < 2)
9655   {
9656     theDi << "ZNear: " << aCamera->ZNear() << "\n";
9657     theDi << "ZFar: " << aCamera->ZFar() << "\n";
9658     return 0;
9659   }
9660
9661   if (theArgsNb == 3)
9662   {
9663     Standard_Real aNewZNear = Draw::Atof (theArgVec[1]);
9664     Standard_Real aNewZFar  = Draw::Atof (theArgVec[2]);
9665
9666     if (aNewZNear >= aNewZFar)
9667     {
9668       std::cout << theArgVec[0] << ": invalid arguments: znear should be less than zfar.\n";
9669       return 1;
9670     }
9671
9672     if (!aCamera->IsOrthographic() && (aNewZNear <= 0.0 || aNewZFar <= 0.0))
9673     {
9674       std::cout << theArgVec[0] << ": invalid arguments: ";
9675       std::cout << "znear, zfar should be positive for perspective camera.\n";
9676       return 1;
9677     }
9678
9679     aCamera->SetZRange (aNewZNear, aNewZFar);
9680   }
9681   else
9682   {
9683     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9684     return 1;
9685   }
9686
9687   aCurrentView->Redraw();
9688
9689   return 0;
9690 }
9691
9692 //===============================================================================================
9693 //function : VAutoZFit
9694 //purpose  :
9695 //===============================================================================================
9696 static int VAutoZFit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
9697 {
9698   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
9699
9700   if (aCurrentView.IsNull())
9701   {
9702     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
9703     return 1;
9704   }
9705
9706   Standard_Real aScale = aCurrentView->AutoZFitScaleFactor();
9707
9708   if (theArgsNb > 3)
9709   {
9710     std::cout << theArgVec[0] << ": wrong command arguments. Type help for more information.\n";
9711     return 1;
9712   }
9713
9714   if (theArgsNb < 2)
9715   {
9716     theDi << "Auto z-fit mode: \n"
9717           << "On: " << (aCurrentView->AutoZFitMode() ? "enabled" : "disabled") << "\n"
9718           << "Scale: " << aScale << "\n";
9719     return 0;
9720   }
9721
9722   Standard_Boolean isOn = Draw::Atoi (theArgVec[1]) == 1;
9723
9724   if (theArgsNb >= 3)
9725   {
9726     aScale = Draw::Atoi (theArgVec[2]);
9727   }
9728
9729   aCurrentView->SetAutoZFitMode (isOn, aScale);
9730   aCurrentView->AutoZFit();
9731   aCurrentView->Redraw();
9732
9733   return 0;
9734 }
9735
9736 //! Auxiliary function to print projection type
9737 inline const char* projTypeName (Graphic3d_Camera::Projection theProjType)
9738 {
9739   switch (theProjType)
9740   {
9741     case Graphic3d_Camera::Projection_Orthographic: return "orthographic";
9742     case Graphic3d_Camera::Projection_Perspective:  return "perspective";
9743     case Graphic3d_Camera::Projection_Stereo:       return "stereoscopic";
9744     case Graphic3d_Camera::Projection_MonoLeftEye:  return "monoLeftEye";
9745     case Graphic3d_Camera::Projection_MonoRightEye: return "monoRightEye";
9746   }
9747   return "UNKNOWN";
9748 }
9749
9750 //===============================================================================================
9751 //function : VCamera
9752 //purpose  :
9753 //===============================================================================================
9754 static int VCamera (Draw_Interpretor& theDI,
9755                     Standard_Integer  theArgsNb,
9756                     const char**      theArgVec)
9757 {
9758   Handle(V3d_View) aView = ViewerTest::CurrentView();
9759   if (aView.IsNull())
9760   {
9761     std::cout << "Error: no active view.\n";
9762     return 1;
9763   }
9764
9765   Handle(Graphic3d_Camera) aCamera = aView->Camera();
9766   if (theArgsNb < 2)
9767   {
9768     theDI << "ProjType:   " << projTypeName (aCamera->ProjectionType()) << "\n";
9769     theDI << "FOVy:       " << aCamera->FOVy() << "\n";
9770     theDI << "Distance:   " << aCamera->Distance() << "\n";
9771     theDI << "IOD:        " << aCamera->IOD() << "\n";
9772     theDI << "IODType:    " << (aCamera->GetIODType() == Graphic3d_Camera::IODType_Absolute   ? "absolute" : "relative") << "\n";
9773     theDI << "ZFocus:     " << aCamera->ZFocus() << "\n";
9774     theDI << "ZFocusType: " << (aCamera->ZFocusType() == Graphic3d_Camera::FocusType_Absolute ? "absolute" : "relative") << "\n";
9775     return 0;
9776   }
9777
9778   TCollection_AsciiString aPrsName;
9779   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
9780   {
9781     Standard_CString        anArg = theArgVec[anArgIter];
9782     TCollection_AsciiString anArgCase (anArg);
9783     anArgCase.LowerCase();
9784     if (anArgCase == "-proj"
9785      || anArgCase == "-projection"
9786      || anArgCase == "-projtype"
9787      || anArgCase == "-projectiontype")
9788     {
9789       theDI << projTypeName (aCamera->ProjectionType()) << " ";
9790     }
9791     else if (anArgCase == "-ortho"
9792           || anArgCase == "-orthographic")
9793     {
9794       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Orthographic);
9795     }
9796     else if (anArgCase == "-persp"
9797           || anArgCase == "-perspective"
9798           || anArgCase == "-perspmono"
9799           || anArgCase == "-perspectivemono"
9800           || anArgCase == "-mono")
9801     {
9802       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
9803     }
9804     else if (anArgCase == "-stereo"
9805           || anArgCase == "-stereoscopic"
9806           || anArgCase == "-perspstereo"
9807           || anArgCase == "-perspectivestereo")
9808     {
9809       aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
9810     }
9811     else if (anArgCase == "-left"
9812           || anArgCase == "-lefteye"
9813           || anArgCase == "-monoleft"
9814           || anArgCase == "-monolefteye"
9815           || anArgCase == "-perpsleft"
9816           || anArgCase == "-perpslefteye")
9817     {
9818       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoLeftEye);
9819     }
9820     else if (anArgCase == "-right"
9821           || anArgCase == "-righteye"
9822           || anArgCase == "-monoright"
9823           || anArgCase == "-monorighteye"
9824           || anArgCase == "-perpsright")
9825     {
9826       aCamera->SetProjectionType (Graphic3d_Camera::Projection_MonoRightEye);
9827     }
9828     else if (anArgCase == "-dist"
9829           || anArgCase == "-distance")
9830     {
9831       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9832       if (anArgValue != NULL
9833       && *anArgValue != '-')
9834       {
9835         ++anArgIter;
9836         aCamera->SetDistance (Draw::Atof (anArgValue));
9837         continue;
9838       }
9839       theDI << aCamera->Distance() << " ";
9840     }
9841     else if (anArgCase == "-iod")
9842     {
9843       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9844       if (anArgValue != NULL
9845       && *anArgValue != '-')
9846       {
9847         ++anArgIter;
9848         aCamera->SetIOD (aCamera->GetIODType(), Draw::Atof (anArgValue));
9849         continue;
9850       }
9851       theDI << aCamera->IOD() << " ";
9852     }
9853     else if (anArgCase == "-iodtype")
9854     {
9855       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9856       TCollection_AsciiString anValueCase (anArgValue);
9857       anValueCase.LowerCase();
9858       if (anValueCase == "abs"
9859        || anValueCase == "absolute")
9860       {
9861         ++anArgIter;
9862         aCamera->SetIOD (Graphic3d_Camera::IODType_Absolute, aCamera->IOD());
9863         continue;
9864       }
9865       else if (anValueCase == "rel"
9866             || anValueCase == "relative")
9867       {
9868         ++anArgIter;
9869         aCamera->SetIOD (Graphic3d_Camera::IODType_Relative, aCamera->IOD());
9870         continue;
9871       }
9872       else if (*anArgValue != '-')
9873       {
9874         std::cout << "Error: unknown IOD type '" << anArgValue << "'\n";
9875         return 1;
9876       }
9877       switch (aCamera->GetIODType())
9878       {
9879         case Graphic3d_Camera::IODType_Absolute: theDI << "absolute "; break;
9880         case Graphic3d_Camera::IODType_Relative: theDI << "relative "; break;
9881       }
9882     }
9883     else if (anArgCase == "-zfocus")
9884     {
9885       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9886       if (anArgValue != NULL
9887       && *anArgValue != '-')
9888       {
9889         ++anArgIter;
9890         aCamera->SetZFocus (aCamera->ZFocusType(), Draw::Atof (anArgValue));
9891         continue;
9892       }
9893       theDI << aCamera->ZFocus() << " ";
9894     }
9895     else if (anArgCase == "-zfocustype")
9896     {
9897       Standard_CString        anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : "";
9898       TCollection_AsciiString anValueCase (anArgValue);
9899       anValueCase.LowerCase();
9900       if (anValueCase == "abs"
9901        || anValueCase == "absolute")
9902       {
9903         ++anArgIter;
9904         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Absolute, aCamera->ZFocus());
9905         continue;
9906       }
9907       else if (anValueCase == "rel"
9908             || anValueCase == "relative")
9909       {
9910         ++anArgIter;
9911         aCamera->SetZFocus (Graphic3d_Camera::FocusType_Relative, aCamera->ZFocus());
9912         continue;
9913       }
9914       else if (*anArgValue != '-')
9915       {
9916         std::cout << "Error: unknown ZFocus type '" << anArgValue << "'\n";
9917         return 1;
9918       }
9919       switch (aCamera->ZFocusType())
9920       {
9921         case Graphic3d_Camera::FocusType_Absolute: theDI << "absolute "; break;
9922         case Graphic3d_Camera::FocusType_Relative: theDI << "relative "; break;
9923       }
9924     }
9925     else if (anArgCase == "-fov"
9926           || anArgCase == "-fovy")
9927     {
9928       Standard_CString anArgValue = (anArgIter + 1 < theArgsNb) ? theArgVec[anArgIter + 1] : NULL;
9929       if (anArgValue != NULL
9930       && *anArgValue != '-')
9931       {
9932         ++anArgIter;
9933         aCamera->SetFOVy (Draw::Atof (anArgValue));
9934         continue;
9935       }
9936       theDI << aCamera->FOVy() << " ";
9937     }
9938     else if (aPrsName.IsEmpty()
9939          && !anArgCase.StartsWith ("-"))
9940     {
9941       aPrsName = anArg;
9942     }
9943     else
9944     {
9945       std::cout << "Error: unknown argument '" << anArg << "'\n";
9946       return 1;
9947     }
9948   }
9949
9950   if (aPrsName.IsEmpty()
9951    || theArgsNb > 2)
9952   {
9953     aView->AutoZFit();
9954     aView->Redraw();
9955   }
9956
9957   if (!aPrsName.IsEmpty())
9958   {
9959     Handle(AIS_CameraFrustum) aCameraFrustum;
9960     if (GetMapOfAIS().IsBound2 (aPrsName))
9961     {
9962       // find existing object
9963       aCameraFrustum = Handle(AIS_CameraFrustum)::DownCast (GetMapOfAIS().Find2 (theArgVec[1]));
9964       if (aCameraFrustum.IsNull())
9965       {
9966         std::cout << "Error: object '" << aPrsName << "'is already defined and is not a camera frustum!\n";
9967         return 1;
9968       }
9969     }
9970
9971     if (aCameraFrustum.IsNull())
9972     {
9973       aCameraFrustum = new AIS_CameraFrustum();
9974     }
9975     else
9976     {
9977       // not include displayed object of old camera frustum in the new one.
9978       ViewerTest::GetAISContext()->Erase (aCameraFrustum, false);
9979       aView->ZFitAll();
9980     }
9981     aCameraFrustum->SetCameraFrustum (aView->Camera());
9982
9983     ViewerTest::Display (aPrsName, aCameraFrustum);
9984   }
9985
9986   return 0;
9987 }
9988
9989 //! Parse stereo output mode
9990 inline Standard_Boolean parseStereoMode (Standard_CString      theArg,
9991                                          Graphic3d_StereoMode& theMode)
9992 {
9993   TCollection_AsciiString aFlag (theArg);
9994   aFlag.LowerCase();
9995   if (aFlag == "quadbuffer")
9996   {
9997     theMode = Graphic3d_StereoMode_QuadBuffer;
9998   }
9999   else if (aFlag == "anaglyph")
10000   {
10001     theMode = Graphic3d_StereoMode_Anaglyph;
10002   }
10003   else if (aFlag == "row"
10004         || aFlag == "rowinterlaced")
10005   {
10006     theMode = Graphic3d_StereoMode_RowInterlaced;
10007   }
10008   else if (aFlag == "col"
10009         || aFlag == "colinterlaced"
10010         || aFlag == "columninterlaced")
10011   {
10012     theMode = Graphic3d_StereoMode_ColumnInterlaced;
10013   }
10014   else if (aFlag == "chess"
10015         || aFlag == "chessboard")
10016   {
10017     theMode = Graphic3d_StereoMode_ChessBoard;
10018   }
10019   else if (aFlag == "sbs"
10020         || aFlag == "sidebyside")
10021   {
10022     theMode = Graphic3d_StereoMode_SideBySide;
10023   }
10024   else if (aFlag == "ou"
10025         || aFlag == "overunder")
10026   {
10027     theMode = Graphic3d_StereoMode_OverUnder;
10028   }
10029   else if (aFlag == "pageflip"
10030         || aFlag == "softpageflip")
10031   {
10032     theMode = Graphic3d_StereoMode_SoftPageFlip;
10033   }
10034   else
10035   {
10036     return Standard_False;
10037   }
10038   return Standard_True;
10039 }
10040
10041 //! Parse anaglyph filter
10042 inline Standard_Boolean parseAnaglyphFilter (Standard_CString                     theArg,
10043                                              Graphic3d_RenderingParams::Anaglyph& theFilter)
10044 {
10045   TCollection_AsciiString aFlag (theArg);
10046   aFlag.LowerCase();
10047   if (aFlag == "redcyansimple")
10048   {
10049     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10050   }
10051   else if (aFlag == "redcyan"
10052         || aFlag == "redcyanoptimized")
10053   {
10054     theFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized;
10055   }
10056   else if (aFlag == "yellowbluesimple")
10057   {
10058     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple;
10059   }
10060   else if (aFlag == "yellowblue"
10061         || aFlag == "yellowblueoptimized")
10062   {
10063     theFilter = Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized;
10064   }
10065   else if (aFlag == "greenmagenta"
10066         || aFlag == "greenmagentasimple")
10067   {
10068     theFilter = Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple;
10069   }
10070   else
10071   {
10072     return Standard_False;
10073   }
10074   return Standard_True;
10075 }
10076
10077 //==============================================================================
10078 //function : VStereo
10079 //purpose  :
10080 //==============================================================================
10081
10082 static int VStereo (Draw_Interpretor& theDI,
10083                     Standard_Integer  theArgNb,
10084                     const char**      theArgVec)
10085 {
10086   Handle(V3d_View) aView = ViewerTest::CurrentView();
10087   if (theArgNb < 2)
10088   {
10089     if (aView.IsNull())
10090     {
10091       std::cout << "Error: no active viewer!\n";
10092       return 0;
10093     }
10094
10095     Standard_Boolean isActive = ViewerTest_myDefaultCaps.contextStereo;
10096     theDI << "Stereo " << (isActive ? "ON" : "OFF") << "\n";
10097     if (isActive)
10098     {
10099       TCollection_AsciiString aMode;
10100       switch (aView->RenderingParams().StereoMode)
10101       {
10102         case Graphic3d_StereoMode_QuadBuffer       : aMode = "quadBuffer";       break;
10103         case Graphic3d_StereoMode_RowInterlaced    : aMode = "rowInterlaced";    break;
10104         case Graphic3d_StereoMode_ColumnInterlaced : aMode = "columnInterlaced"; break;
10105         case Graphic3d_StereoMode_ChessBoard       : aMode = "chessBoard";       break;
10106         case Graphic3d_StereoMode_SideBySide       : aMode = "sideBySide";       break;
10107         case Graphic3d_StereoMode_OverUnder        : aMode = "overUnder";        break;
10108         case Graphic3d_StereoMode_SoftPageFlip     : aMode = "softpageflip";     break;
10109         case Graphic3d_StereoMode_Anaglyph  :
10110           aMode = "anaglyph";
10111           switch (aView->RenderingParams().AnaglyphFilter)
10112           {
10113             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple      : aMode.AssignCat (" (redCyanSimple)");      break;
10114             case Graphic3d_RenderingParams::Anaglyph_RedCyan_Optimized   : aMode.AssignCat (" (redCyan)");            break;
10115             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Simple   : aMode.AssignCat (" (yellowBlueSimple)");   break;
10116             case Graphic3d_RenderingParams::Anaglyph_YellowBlue_Optimized: aMode.AssignCat (" (yellowBlue)");         break;
10117             case Graphic3d_RenderingParams::Anaglyph_GreenMagenta_Simple : aMode.AssignCat (" (greenMagentaSimple)"); break;
10118             default: break;
10119           }
10120         default: break;
10121       }
10122       theDI << "Mode " << aMode << "\n";
10123     }
10124     return 0;
10125   }
10126
10127   Handle(Graphic3d_Camera) aCamera;
10128   Graphic3d_RenderingParams*   aParams   = NULL;
10129   Graphic3d_StereoMode         aMode     = Graphic3d_StereoMode_QuadBuffer;
10130   if (!aView.IsNull())
10131   {
10132     aParams   = &aView->ChangeRenderingParams();
10133     aMode     = aParams->StereoMode;
10134     aCamera   = aView->Camera();
10135   }
10136
10137   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10138   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
10139   {
10140     Standard_CString        anArg = theArgVec[anArgIter];
10141     TCollection_AsciiString aFlag (anArg);
10142     aFlag.LowerCase();
10143     if (anUpdateTool.parseRedrawMode (aFlag))
10144     {
10145       continue;
10146     }
10147     else if (aFlag == "0"
10148           || aFlag == "off")
10149     {
10150       if (++anArgIter < theArgNb)
10151       {
10152         std::cout << "Error: wrong number of arguments!\n";
10153         return 1;
10154       }
10155
10156       if (!aCamera.IsNull()
10157        &&  aCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
10158       {
10159         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Perspective);
10160       }
10161       ViewerTest_myDefaultCaps.contextStereo = Standard_False;
10162       return 0;
10163     }
10164     else if (aFlag == "1"
10165           || aFlag == "on")
10166     {
10167       if (++anArgIter < theArgNb)
10168       {
10169         std::cout << "Error: wrong number of arguments!\n";
10170         return 1;
10171       }
10172
10173       if (!aCamera.IsNull())
10174       {
10175         aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10176       }
10177       ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10178       return 0;
10179     }
10180     else if (aFlag == "-reverse"
10181           || aFlag == "-reversed"
10182           || aFlag == "-swap")
10183     {
10184       Standard_Boolean toEnable = Standard_True;
10185       if (++anArgIter < theArgNb
10186       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
10187       {
10188         --anArgIter;
10189       }
10190       aParams->ToReverseStereo = toEnable;
10191     }
10192     else if (aFlag == "-noreverse"
10193           || aFlag == "-noswap")
10194     {
10195       Standard_Boolean toDisable = Standard_True;
10196       if (++anArgIter < theArgNb
10197       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toDisable))
10198       {
10199         --anArgIter;
10200       }
10201       aParams->ToReverseStereo = !toDisable;
10202     }
10203     else if (aFlag == "-mode"
10204           || aFlag == "-stereomode")
10205     {
10206       if (++anArgIter >= theArgNb
10207       || !parseStereoMode (theArgVec[anArgIter], aMode))
10208       {
10209         std::cout << "Error: syntax error at '" << anArg << "'\n";
10210         return 1;
10211       }
10212
10213       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10214       {
10215         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10216       }
10217     }
10218     else if (aFlag == "-anaglyph"
10219           || aFlag == "-anaglyphfilter")
10220     {
10221       Graphic3d_RenderingParams::Anaglyph aFilter = Graphic3d_RenderingParams::Anaglyph_RedCyan_Simple;
10222       if (++anArgIter >= theArgNb
10223       || !parseAnaglyphFilter (theArgVec[anArgIter], aFilter))
10224       {
10225         std::cout << "Error: syntax error at '" << anArg << "'\n";
10226         return 1;
10227       }
10228
10229       aMode = Graphic3d_StereoMode_Anaglyph;
10230       aParams->AnaglyphFilter = aFilter;
10231     }
10232     else if (parseStereoMode (anArg, aMode)) // short syntax
10233     {
10234       if (aMode == Graphic3d_StereoMode_QuadBuffer)
10235       {
10236         ViewerTest_myDefaultCaps.contextStereo = Standard_True;
10237       }
10238     }
10239     else
10240     {
10241       std::cout << "Error: syntax error at '" << anArg << "'\n";
10242       return 1;
10243     }
10244   }
10245
10246   if (!aView.IsNull())
10247   {
10248     aParams->StereoMode = aMode;
10249     aCamera->SetProjectionType (Graphic3d_Camera::Projection_Stereo);
10250   }
10251   return 0;
10252 }
10253
10254 //===============================================================================================
10255 //function : VDefaults
10256 //purpose  :
10257 //===============================================================================================
10258 static int VDefaults (Draw_Interpretor& theDi,
10259                       Standard_Integer  theArgsNb,
10260                       const char**      theArgVec)
10261 {
10262   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
10263   if (aCtx.IsNull())
10264   {
10265     std::cerr << "No active viewer!\n";
10266     return 1;
10267   }
10268
10269   Handle(Prs3d_Drawer) aDefParams = aCtx->DefaultDrawer();
10270   if (theArgsNb < 2)
10271   {
10272     if (aDefParams->TypeOfDeflection() == Aspect_TOD_RELATIVE)
10273     {
10274       theDi << "DeflType:           relative\n"
10275             << "DeviationCoeff:     " << aDefParams->DeviationCoefficient() << "\n";
10276     }
10277     else
10278     {
10279       theDi << "DeflType:           absolute\n"
10280             << "AbsoluteDeflection: " << aDefParams->MaximalChordialDeviation() << "\n";
10281     }
10282     theDi << "AngularDeflection:  " << (180.0 * aDefParams->HLRAngle() / M_PI) << "\n";
10283     theDi << "AutoTriangulation:  " << (aDefParams->IsAutoTriangulation() ? "on" : "off") << "\n";
10284     return 0;
10285   }
10286
10287   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
10288   {
10289     TCollection_AsciiString anArg (theArgVec[anArgIter]);
10290     anArg.UpperCase();
10291     if (anArg == "-ABSDEFL"
10292      || anArg == "-ABSOLUTEDEFLECTION"
10293      || anArg == "-DEFL"
10294      || anArg == "-DEFLECTION")
10295     {
10296       if (++anArgIter >= theArgsNb)
10297       {
10298         std::cout << "Error: wrong syntax at " << anArg << "\n";
10299         return 1;
10300       }
10301       aDefParams->SetTypeOfDeflection         (Aspect_TOD_ABSOLUTE);
10302       aDefParams->SetMaximalChordialDeviation (Draw::Atof (theArgVec[anArgIter]));
10303     }
10304     else if (anArg == "-RELDEFL"
10305           || anArg == "-RELATIVEDEFLECTION"
10306           || anArg == "-DEVCOEFF"
10307           || anArg == "-DEVIATIONCOEFF"
10308           || anArg == "-DEVIATIONCOEFFICIENT")
10309     {
10310       if (++anArgIter >= theArgsNb)
10311       {
10312         std::cout << "Error: wrong syntax at " << anArg << "\n";
10313         return 1;
10314       }
10315       aDefParams->SetTypeOfDeflection     (Aspect_TOD_RELATIVE);
10316       aDefParams->SetDeviationCoefficient (Draw::Atof (theArgVec[anArgIter]));
10317     }
10318     else if (anArg == "-ANGDEFL"
10319           || anArg == "-ANGULARDEFL"
10320           || anArg == "-ANGULARDEFLECTION")
10321     {
10322       if (++anArgIter >= theArgsNb)
10323       {
10324         std::cout << "Error: wrong syntax at " << anArg << "\n";
10325         return 1;
10326       }
10327       // currently HLRDeviationAngle is used instead of DeviationAngle in most places
10328       aDefParams->SetHLRAngle (M_PI * Draw::Atof (theArgVec[anArgIter]) / 180.0);
10329     }
10330     else if (anArg == "-AUTOTR"
10331           || anArg == "-AUTOTRIANG"
10332           || anArg == "-AUTOTRIANGULATION")
10333     {
10334       if (++anArgIter >= theArgsNb)
10335       {
10336         std::cout << "Error: wrong syntax at " << anArg << "\n";
10337         return 1;
10338       }
10339       TCollection_AsciiString aValue (theArgVec[anArgIter]);
10340       aValue.LowerCase();
10341       if (aValue == "on"
10342        || aValue == "1")
10343       {
10344         aDefParams->SetAutoTriangulation (Standard_True);
10345       }
10346       else if (aValue == "off"
10347             || aValue == "0")
10348       {
10349         aDefParams->SetAutoTriangulation (Standard_False);
10350       }
10351     }
10352     else
10353     {
10354       std::cerr << "Warning, unknown argument '" << anArg.ToCString() << "'\n";
10355     }
10356   }
10357
10358   return 0;
10359 }
10360
10361 //! Auxiliary method
10362 inline void addLight (const Handle(V3d_Light)& theLightNew,
10363                       const Graphic3d_ZLayerId theLayer,
10364                       const Standard_Boolean   theIsGlobal)
10365 {
10366   if (theLightNew.IsNull())
10367   {
10368     return;
10369   }
10370
10371   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10372   if (theLayer == Graphic3d_ZLayerId_UNKNOWN)
10373   {
10374     aViewer->AddLight (theLightNew);
10375     if (theIsGlobal)
10376     {
10377       aViewer->SetLightOn (theLightNew);
10378     }
10379     else
10380     {
10381       ViewerTest::CurrentView()->SetLightOn (theLightNew);
10382     }
10383   }
10384   else
10385   {
10386     Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (theLayer);
10387     if (aSettings.Lights().IsNull())
10388     {
10389       aSettings.SetLights (new Graphic3d_LightSet());
10390     }
10391     aSettings.Lights()->Add (theLightNew);
10392     aViewer->SetZLayerSettings (theLayer, aSettings);
10393   }
10394 }
10395
10396 //! Auxiliary method
10397 inline Standard_Integer getLightId (const TCollection_AsciiString& theArgNext)
10398 {
10399   TCollection_AsciiString anArgNextCase (theArgNext);
10400   anArgNextCase.UpperCase();
10401   if (anArgNextCase.Length() > 5
10402    && anArgNextCase.SubString (1, 5).IsEqual ("LIGHT"))
10403   {
10404     return theArgNext.SubString (6, theArgNext.Length()).IntegerValue();
10405   }
10406   else
10407   {
10408     return theArgNext.IntegerValue();
10409   }
10410 }
10411
10412 //===============================================================================================
10413 //function : VLight
10414 //purpose  :
10415 //===============================================================================================
10416 static int VLight (Draw_Interpretor& theDi,
10417                    Standard_Integer  theArgsNb,
10418                    const char**      theArgVec)
10419 {
10420   Handle(V3d_View)   aView   = ViewerTest::CurrentView();
10421   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
10422   if (aView.IsNull()
10423    || aViewer.IsNull())
10424   {
10425     std::cerr << "No active viewer!\n";
10426     return 1;
10427   }
10428
10429   Standard_Real anXYZ[3]   = {};
10430   Standard_Real anAtten[2] = {};
10431   if (theArgsNb < 2)
10432   {
10433     // print lights info
10434     Standard_Integer aLightId = 0;
10435     for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightId)
10436     {
10437       Handle(V3d_Light) aLight = aLightIter.Value();
10438       const Quantity_Color aColor = aLight->Color();
10439       theDi << "Light #" << aLightId
10440             << (!aLight->Name().IsEmpty() ? (TCollection_AsciiString(" ") + aLight->Name()) : "")
10441             << " [" << aLight->GetId() << "]" << "\n";
10442       switch (aLight->Type())
10443       {
10444         case V3d_AMBIENT:
10445         {
10446           theDi << "  Type:       Ambient\n";
10447           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10448           break;
10449         }
10450         case V3d_DIRECTIONAL:
10451         {
10452           theDi << "  Type:       Directional\n";
10453           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10454           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10455           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10456           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10457           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10458           break;
10459         }
10460         case V3d_POSITIONAL:
10461         {
10462           theDi << "  Type:       Positional\n";
10463           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10464           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10465           theDi << "  Smoothness: " << aLight->Smoothness() << "\n";
10466           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10467           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10468           aLight->Attenuation (anAtten[0], anAtten[1]);
10469           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10470           break;
10471         }
10472         case V3d_SPOT:
10473         {
10474           theDi << "  Type:       Spot\n";
10475           theDi << "  Intensity:  " << aLight->Intensity() << "\n";
10476           theDi << "  Headlight:  " << (aLight->Headlight() ? "TRUE" : "FALSE") << "\n";
10477           aLight->Position  (anXYZ[0], anXYZ[1], anXYZ[2]);
10478           theDi << "  Position:   " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10479           aLight->Direction (anXYZ[0], anXYZ[1], anXYZ[2]);
10480           theDi << "  Direction:  " << anXYZ[0] << ", " << anXYZ[1] << ", " << anXYZ[2] << "\n";
10481           aLight->Attenuation (anAtten[0], anAtten[1]);
10482           theDi << "  Atten.:     " << anAtten[0] << " " << anAtten[1] << "\n";
10483           theDi << "  Angle:      " << (aLight->Angle() * 180.0 / M_PI) << "\n";
10484           theDi << "  Exponent:   " << aLight->Concentration() << "\n";
10485           break;
10486         }
10487         default:
10488         {
10489           theDi << "  Type:       UNKNOWN\n";
10490           break;
10491         }
10492       }
10493       theDi << "  Color:      " << aColor.Red() << ", " << aColor.Green() << ", " << aColor.Blue() << " [" << Quantity_Color::StringName (aColor.Name()) << "]\n";
10494     }
10495   }
10496
10497   Handle(V3d_Light) aLightNew;
10498   Handle(V3d_Light) aLightOld;
10499   Graphic3d_ZLayerId aLayer = Graphic3d_ZLayerId_UNKNOWN;
10500   Standard_Boolean  isGlobal = Standard_True;
10501   Standard_Boolean  toCreate = Standard_False;
10502   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
10503   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
10504   {
10505     Handle(V3d_Light) aLightCurr = aLightNew.IsNull() ? aLightOld : aLightNew;
10506
10507     TCollection_AsciiString aName, aValue;
10508     const TCollection_AsciiString anArg (theArgVec[anArgIt]);
10509     TCollection_AsciiString anArgCase (anArg);
10510     anArgCase.UpperCase();
10511     if (anUpdateTool.parseRedrawMode (anArg))
10512     {
10513       continue;
10514     }
10515
10516     if (anArgCase.IsEqual ("NEW")
10517      || anArgCase.IsEqual ("ADD")
10518      || anArgCase.IsEqual ("CREATE")
10519      || anArgCase.IsEqual ("-NEW")
10520      || anArgCase.IsEqual ("-ADD")
10521      || anArgCase.IsEqual ("-CREATE"))
10522     {
10523       toCreate = Standard_True;
10524     }
10525     else if (anArgCase.IsEqual ("-LAYER")
10526           || anArgCase.IsEqual ("-ZLAYER"))
10527     {
10528       if (++anArgIt >= theArgsNb)
10529       {
10530         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10531         return 1;
10532       }
10533
10534       TCollection_AsciiString aValStr (theArgVec[anArgIt]);
10535       aValStr.LowerCase();
10536       if (aValStr == "default"
10537        || aValStr == "def")
10538       {
10539         aLayer = Graphic3d_ZLayerId_Default;
10540       }
10541       else if (aValStr == "top")
10542       {
10543         aLayer = Graphic3d_ZLayerId_Top;
10544       }
10545       else if (aValStr == "topmost")
10546       {
10547         aLayer = Graphic3d_ZLayerId_Topmost;
10548       }
10549       else if (aValStr == "toposd"
10550             || aValStr == "osd")
10551       {
10552         aLayer = Graphic3d_ZLayerId_TopOSD;
10553       }
10554       else if (aValStr == "botosd"
10555             || aValStr == "bottom")
10556       {
10557         aLayer = Graphic3d_ZLayerId_BotOSD;
10558       }
10559       else if (aValStr.IsIntegerValue())
10560       {
10561         aLayer = Draw::Atoi (theArgVec[anArgIt]);
10562       }
10563       else
10564       {
10565         std::cout << "Wrong syntax at argument '" << anArg << "'!\n";
10566         return 1;
10567       }
10568     }
10569     else if (anArgCase.IsEqual ("GLOB")
10570           || anArgCase.IsEqual ("GLOBAL")
10571           || anArgCase.IsEqual ("-GLOB")
10572           || anArgCase.IsEqual ("-GLOBAL"))
10573     {
10574       isGlobal = Standard_True;
10575     }
10576     else if (anArgCase.IsEqual ("LOC")
10577           || anArgCase.IsEqual ("LOCAL")
10578           || anArgCase.IsEqual ("-LOC")
10579           || anArgCase.IsEqual ("-LOCAL"))
10580     {
10581       isGlobal = Standard_False;
10582     }
10583     else if (anArgCase.IsEqual ("DEF")
10584           || anArgCase.IsEqual ("DEFAULTS")
10585           || anArgCase.IsEqual ("-DEF")
10586           || anArgCase.IsEqual ("-DEFAULTS"))
10587     {
10588       toCreate = Standard_False;
10589       aViewer->SetDefaultLights();
10590     }
10591     else if (anArgCase.IsEqual ("CLR")
10592           || anArgCase.IsEqual ("CLEAR")
10593           || anArgCase.IsEqual ("-CLR")
10594           || anArgCase.IsEqual ("-CLEAR"))
10595     {
10596       toCreate = Standard_False;
10597
10598       TColStd_SequenceOfInteger aLayers;
10599       aViewer->GetAllZLayers (aLayers);
10600       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10601       {
10602         if (aLayeriter.Value() == aLayer
10603          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10604         {
10605           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10606           aSettings.SetLights (Handle(Graphic3d_LightSet)());
10607           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10608           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10609           {
10610             break;
10611           }
10612         }
10613       }
10614
10615       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10616       {
10617         for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More();)
10618         {
10619           Handle(V3d_Light) aLight = aLightIter.Value();
10620           aViewer->DelLight (aLight);
10621           aLightIter = aView->ActiveLightIterator();
10622         }
10623       }
10624     }
10625     else if (anArgCase.IsEqual ("AMB")
10626           || anArgCase.IsEqual ("AMBIENT")
10627           || anArgCase.IsEqual ("AMBLIGHT"))
10628     {
10629       if (!toCreate)
10630       {
10631         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10632         return 1;
10633       }
10634
10635       addLight (aLightNew, aLayer, isGlobal);
10636       toCreate  = Standard_False;
10637       aLightNew = new V3d_AmbientLight();
10638     }
10639     else if (anArgCase.IsEqual ("DIRECTIONAL")
10640           || anArgCase.IsEqual ("DIRLIGHT"))
10641     {
10642       if (!toCreate)
10643       {
10644         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10645         return 1;
10646       }
10647
10648       addLight (aLightNew, aLayer, isGlobal);
10649       toCreate  = Standard_False;
10650       aLightNew = new V3d_DirectionalLight();
10651     }
10652     else if (anArgCase.IsEqual ("SPOT")
10653           || anArgCase.IsEqual ("SPOTLIGHT"))
10654     {
10655       if (!toCreate)
10656       {
10657         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10658         return 1;
10659       }
10660
10661       addLight (aLightNew, aLayer, isGlobal);
10662       toCreate  = Standard_False;
10663       aLightNew = new V3d_SpotLight (gp_Pnt (0.0, 0.0, 0.0));
10664     }
10665     else if (anArgCase.IsEqual ("POSLIGHT")
10666           || anArgCase.IsEqual ("POSITIONAL"))
10667     {
10668       if (!toCreate)
10669       {
10670         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10671         return 1;
10672       }
10673
10674       addLight (aLightNew, aLayer, isGlobal);
10675       toCreate  = Standard_False;
10676       aLightNew = new V3d_PositionalLight (gp_Pnt (0.0, 0.0, 0.0));
10677     }
10678     else if (anArgCase.IsEqual ("CHANGE")
10679           || anArgCase.IsEqual ("-CHANGE"))
10680     {
10681       if (++anArgIt >= theArgsNb)
10682       {
10683         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10684         return 1;
10685       }
10686
10687       addLight (aLightNew, aLayer, isGlobal);
10688       aLightNew.Nullify();
10689       const Standard_Integer aLightId = getLightId (theArgVec[anArgIt]);
10690       Standard_Integer aLightIt = 0;
10691       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10692       {
10693         if (aLightIt == aLightId)
10694         {
10695           aLightOld = aLightIter.Value();
10696           break;
10697         }
10698       }
10699
10700       if (aLightOld.IsNull())
10701       {
10702         std::cerr << "Light " << theArgVec[anArgIt] << " is undefined!\n";
10703         return 1;
10704       }
10705     }
10706     else if (anArgCase.IsEqual ("DEL")
10707           || anArgCase.IsEqual ("DELETE")
10708           || anArgCase.IsEqual ("-DEL")
10709           || anArgCase.IsEqual ("-DELETE"))
10710     {
10711       Handle(V3d_Light) aLightDel;
10712       if (++anArgIt >= theArgsNb)
10713       {
10714         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10715         return 1;
10716       }
10717
10718       const TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10719       const Standard_Integer aLightDelId = getLightId (theArgVec[anArgIt]);
10720       Standard_Integer aLightIt = 0;
10721       for (V3d_ListOfLightIterator aLightIter (aView->ActiveLightIterator()); aLightIter.More(); aLightIter.Next(), ++aLightIt)
10722       {
10723         aLightDel = aLightIter.Value();
10724         if (aLightIt == aLightDelId)
10725         {
10726           break;
10727         }
10728       }
10729       if (aLightDel.IsNull())
10730       {
10731         continue;
10732       }
10733
10734       TColStd_SequenceOfInteger aLayers;
10735       aViewer->GetAllZLayers (aLayers);
10736       for (TColStd_SequenceOfInteger::Iterator aLayeriter (aLayers); aLayeriter.More(); aLayeriter.Next())
10737       {
10738         if (aLayeriter.Value() == aLayer
10739          || aLayer == Graphic3d_ZLayerId_UNKNOWN)
10740         {
10741           Graphic3d_ZLayerSettings aSettings = aViewer->ZLayerSettings (aLayeriter.Value());
10742           if (!aSettings.Lights().IsNull())
10743           {
10744             aSettings.Lights()->Remove (aLightDel);
10745             if (aSettings.Lights()->IsEmpty())
10746             {
10747               aSettings.SetLights (Handle(Graphic3d_LightSet)());
10748             }
10749           }
10750           aViewer->SetZLayerSettings (aLayeriter.Value(), aSettings);
10751           if (aLayer != Graphic3d_ZLayerId_UNKNOWN)
10752           {
10753             break;
10754           }
10755         }
10756       }
10757
10758       if (aLayer == Graphic3d_ZLayerId_UNKNOWN)
10759       {
10760         aViewer->DelLight (aLightDel);
10761       }
10762     }
10763     else if (anArgCase.IsEqual ("COLOR")
10764           || anArgCase.IsEqual ("COLOUR")
10765           || anArgCase.IsEqual ("-COLOR")
10766           || anArgCase.IsEqual ("-COLOUR"))
10767     {
10768       if (++anArgIt >= theArgsNb
10769        || aLightCurr.IsNull())
10770       {
10771         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10772         return 1;
10773       }
10774
10775       TCollection_AsciiString anArgNext (theArgVec[anArgIt]);
10776       anArgNext.UpperCase();
10777       const Quantity_Color aColor = ViewerTest::GetColorFromName (anArgNext.ToCString());
10778       aLightCurr->SetColor (aColor);
10779     }
10780     else if (anArgCase.IsEqual ("POS")
10781           || anArgCase.IsEqual ("POSITION")
10782           || anArgCase.IsEqual ("-POS")
10783           || anArgCase.IsEqual ("-POSITION"))
10784     {
10785       if ((anArgIt + 3) >= theArgsNb
10786        || aLightCurr.IsNull()
10787        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10788         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10789       {
10790         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10791         return 1;
10792       }
10793
10794       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10795       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10796       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10797       aLightCurr->SetPosition (anXYZ[0], anXYZ[1], anXYZ[2]);
10798     }
10799     else if (anArgCase.IsEqual ("DIR")
10800           || anArgCase.IsEqual ("DIRECTION")
10801           || anArgCase.IsEqual ("-DIR")
10802           || anArgCase.IsEqual ("-DIRECTION"))
10803     {
10804       if ((anArgIt + 3) >= theArgsNb
10805        || aLightCurr.IsNull()
10806        || (aLightCurr->Type() != Graphic3d_TOLS_DIRECTIONAL
10807         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10808       {
10809         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10810         return 1;
10811       }
10812
10813       anXYZ[0] = Atof (theArgVec[++anArgIt]);
10814       anXYZ[1] = Atof (theArgVec[++anArgIt]);
10815       anXYZ[2] = Atof (theArgVec[++anArgIt]);
10816       aLightCurr->SetDirection (anXYZ[0], anXYZ[1], anXYZ[2]);
10817     }
10818     else if (anArgCase.IsEqual ("SM")
10819           || anArgCase.IsEqual ("SMOOTHNESS")
10820           || anArgCase.IsEqual ("-SM")
10821           || anArgCase.IsEqual ("-SMOOTHNESS"))
10822     {
10823       if (++anArgIt >= theArgsNb
10824        || aLightCurr.IsNull())
10825       {
10826         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10827         return 1;
10828       }
10829
10830       Standard_ShortReal aSmoothness = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10831       if (Abs (aSmoothness) <= ShortRealEpsilon())
10832       {
10833         aLightCurr->SetIntensity (1.f);
10834       }
10835       else if (Abs (aLightCurr->Smoothness()) <= ShortRealEpsilon())
10836       {
10837         aLightCurr->SetIntensity ((aSmoothness * aSmoothness) / 3.f);
10838       }
10839       else
10840       {
10841         Standard_ShortReal aSmoothnessRatio = static_cast<Standard_ShortReal> (aSmoothness / aLightCurr->Smoothness());
10842         aLightCurr->SetIntensity (aLightCurr->Intensity() / (aSmoothnessRatio * aSmoothnessRatio));
10843       }
10844
10845       if (aLightCurr->Type() == Graphic3d_TOLS_POSITIONAL)
10846       {
10847         aLightCurr->SetSmoothRadius (aSmoothness);
10848       }
10849       else if (aLightCurr->Type() == Graphic3d_TOLS_DIRECTIONAL)
10850       {
10851         aLightCurr->SetSmoothAngle (aSmoothness);
10852       }
10853     }
10854     else if (anArgCase.IsEqual ("INT")
10855           || anArgCase.IsEqual ("INTENSITY")
10856           || anArgCase.IsEqual ("-INT")
10857           || anArgCase.IsEqual ("-INTENSITY"))
10858     {
10859       if (++anArgIt >= theArgsNb
10860        || aLightCurr.IsNull())
10861       {
10862         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10863         return 1;
10864       }
10865
10866       Standard_ShortReal aIntensity = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10867       aLightCurr->SetIntensity (aIntensity);
10868     }
10869     else if (anArgCase.IsEqual ("ANG")
10870           || anArgCase.IsEqual ("ANGLE")
10871           || anArgCase.IsEqual ("-ANG")
10872           || anArgCase.IsEqual ("-ANGLE"))
10873     {
10874       if (++anArgIt >= theArgsNb
10875        || aLightCurr.IsNull()
10876        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10877       {
10878         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10879         return 1;
10880       }
10881
10882       Standard_ShortReal anAngle = (Standard_ShortReal )Atof (theArgVec[anArgIt]);
10883       aLightCurr->SetAngle (Standard_ShortReal (anAngle / 180.0 * M_PI));
10884     }
10885     else if (anArgCase.IsEqual ("CONSTATTEN")
10886           || anArgCase.IsEqual ("CONSTATTENUATION")
10887           || anArgCase.IsEqual ("-CONSTATTEN")
10888           || anArgCase.IsEqual ("-CONSTATTENUATION"))
10889     {
10890       if (++anArgIt >= theArgsNb
10891        || aLightCurr.IsNull()
10892        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10893         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10894       {
10895         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10896         return 1;
10897       }
10898
10899       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10900       anAtten[0] = Atof (theArgVec[anArgIt]);
10901       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10902     }
10903     else if (anArgCase.IsEqual ("LINATTEN")
10904           || anArgCase.IsEqual ("LINEARATTEN")
10905           || anArgCase.IsEqual ("LINEARATTENUATION")
10906           || anArgCase.IsEqual ("-LINATTEN")
10907           || anArgCase.IsEqual ("-LINEARATTEN")
10908           || anArgCase.IsEqual ("-LINEARATTENUATION"))
10909     {
10910       if (++anArgIt >= theArgsNb
10911        || aLightCurr.IsNull()
10912        || (aLightCurr->Type() != Graphic3d_TOLS_POSITIONAL
10913         && aLightCurr->Type() != Graphic3d_TOLS_SPOT))
10914       {
10915         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10916         return 1;
10917       }
10918
10919       aLightCurr->Attenuation (anAtten[0], anAtten[1]);
10920       anAtten[1] = Atof (theArgVec[anArgIt]);
10921       aLightCurr->SetAttenuation ((Standard_ShortReal )anAtten[0], (Standard_ShortReal )anAtten[1]);
10922     }
10923     else if (anArgCase.IsEqual ("EXP")
10924           || anArgCase.IsEqual ("EXPONENT")
10925           || anArgCase.IsEqual ("SPOTEXP")
10926           || anArgCase.IsEqual ("SPOTEXPONENT")
10927           || anArgCase.IsEqual ("-EXP")
10928           || anArgCase.IsEqual ("-EXPONENT")
10929           || anArgCase.IsEqual ("-SPOTEXP")
10930           || anArgCase.IsEqual ("-SPOTEXPONENT"))
10931     {
10932       if (++anArgIt >= theArgsNb
10933        || aLightCurr.IsNull()
10934        || aLightCurr->Type() != Graphic3d_TOLS_SPOT)
10935       {
10936         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10937         return 1;
10938       }
10939
10940       aLightCurr->SetConcentration ((Standard_ShortReal )Atof (theArgVec[anArgIt]));
10941     }
10942     else if (anArgCase.IsEqual ("HEAD")
10943           || anArgCase.IsEqual ("HEADLIGHT")
10944           || anArgCase.IsEqual ("-HEAD")
10945           || anArgCase.IsEqual ("-HEADLIGHT"))
10946     {
10947       if (aLightCurr.IsNull()
10948        || aLightCurr->Type() == Graphic3d_TOLS_AMBIENT)
10949       {
10950         std::cerr << "Wrong syntax at argument '" << anArg << "'!\n";
10951         return 1;
10952       }
10953
10954       Standard_Boolean isHeadLight = Standard_True;
10955       if (anArgIt + 1 < theArgsNb
10956        && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], isHeadLight))
10957       {
10958         ++anArgIt;
10959       }
10960       aLightCurr->SetHeadlight (isHeadLight);
10961     }
10962     else
10963     {
10964       std::cerr << "Warning: unknown argument '" << anArg << "'\n";
10965     }
10966   }
10967
10968   addLight (aLightNew, aLayer, isGlobal);
10969   return 0;
10970 }
10971
10972 //! Read Graphic3d_RenderingParams::PerfCounters flag.
10973 static Standard_Boolean parsePerfStatsFlag (const TCollection_AsciiString& theValue,
10974                                             Standard_Boolean& theToReset,
10975                                             Graphic3d_RenderingParams::PerfCounters& theFlagsRem,
10976                                             Graphic3d_RenderingParams::PerfCounters& theFlagsAdd)
10977 {
10978   Graphic3d_RenderingParams::PerfCounters aFlag = Graphic3d_RenderingParams::PerfCounters_NONE;
10979   TCollection_AsciiString aVal = theValue;
10980   Standard_Boolean toReverse = Standard_False;
10981   if (aVal == "none")
10982   {
10983     theToReset = Standard_True;
10984     return Standard_True;
10985   }
10986   else if (aVal.StartsWith ("-"))
10987   {
10988     toReverse = Standard_True;
10989     aVal = aVal.SubString (2, aVal.Length());
10990   }
10991   else if (aVal.StartsWith ("no"))
10992   {
10993     toReverse = Standard_True;
10994     aVal = aVal.SubString (3, aVal.Length());
10995   }
10996   else if (aVal.StartsWith ("+"))
10997   {
10998     aVal = aVal.SubString (2, aVal.Length());
10999   }
11000   else
11001   {
11002     theToReset = Standard_True;
11003   }
11004
11005   if (     aVal == "fps"
11006         || aVal == "framerate")  aFlag = Graphic3d_RenderingParams::PerfCounters_FrameRate;
11007   else if (aVal == "cpu")        aFlag = Graphic3d_RenderingParams::PerfCounters_CPU;
11008   else if (aVal == "layers")     aFlag = Graphic3d_RenderingParams::PerfCounters_Layers;
11009   else if (aVal == "structs"
11010         || aVal == "structures"
11011         || aVal == "objects")    aFlag = Graphic3d_RenderingParams::PerfCounters_Structures;
11012   else if (aVal == "groups")     aFlag = Graphic3d_RenderingParams::PerfCounters_Groups;
11013   else if (aVal == "arrays")     aFlag = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
11014   else if (aVal == "tris"
11015         || aVal == "triangles")  aFlag = Graphic3d_RenderingParams::PerfCounters_Triangles;
11016   else if (aVal == "pnts"
11017         || aVal == "points")     aFlag = Graphic3d_RenderingParams::PerfCounters_Points;
11018   else if (aVal == "mem"
11019         || aVal == "gpumem"
11020         || aVal == "estimmem")   aFlag = Graphic3d_RenderingParams::PerfCounters_EstimMem;
11021   else if (aVal == "skipimmediate"
11022         || aVal == "noimmediate") aFlag = Graphic3d_RenderingParams::PerfCounters_SkipImmediate;
11023   else if (aVal == "frametime"
11024         || aVal == "frametimers"
11025         || aVal == "time")       aFlag = Graphic3d_RenderingParams::PerfCounters_FrameTime;
11026   else if (aVal == "basic")      aFlag = Graphic3d_RenderingParams::PerfCounters_Basic;
11027   else if (aVal == "extended"
11028         || aVal == "verbose"
11029         || aVal == "extra")      aFlag = Graphic3d_RenderingParams::PerfCounters_Extended;
11030   else if (aVal == "full"
11031         || aVal == "all")        aFlag = Graphic3d_RenderingParams::PerfCounters_All;
11032   else
11033   {
11034     return Standard_False;
11035   }
11036
11037   if (toReverse)
11038   {
11039     theFlagsRem = Graphic3d_RenderingParams::PerfCounters(theFlagsRem | aFlag);
11040   }
11041   else
11042   {
11043     theFlagsAdd = Graphic3d_RenderingParams::PerfCounters(theFlagsAdd | aFlag);
11044   }
11045   return Standard_True;
11046 }
11047
11048 //! Read Graphic3d_RenderingParams::PerfCounters flags.
11049 static Standard_Boolean convertToPerfStatsFlags (const TCollection_AsciiString& theValue,
11050                                                  Graphic3d_RenderingParams::PerfCounters& theFlags)
11051 {
11052   TCollection_AsciiString aValue = theValue;
11053   Graphic3d_RenderingParams::PerfCounters aFlagsRem = Graphic3d_RenderingParams::PerfCounters_NONE;
11054   Graphic3d_RenderingParams::PerfCounters aFlagsAdd = Graphic3d_RenderingParams::PerfCounters_NONE;
11055   Standard_Boolean toReset = Standard_False;
11056   for (;;)
11057   {
11058     Standard_Integer aSplitPos = aValue.Search ("|");
11059     if (aSplitPos <= 0)
11060     {
11061       if (!parsePerfStatsFlag (aValue, toReset, aFlagsRem, aFlagsAdd))
11062       {
11063         return Standard_False;
11064       }
11065       if (toReset)
11066       {
11067         theFlags = Graphic3d_RenderingParams::PerfCounters_NONE;
11068       }
11069       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags |  aFlagsAdd);
11070       theFlags = Graphic3d_RenderingParams::PerfCounters(theFlags & ~aFlagsRem);
11071       return Standard_True;
11072     }
11073
11074     if (aSplitPos > 1)
11075     {
11076       TCollection_AsciiString aSubValue = aValue.SubString (1, aSplitPos - 1);
11077       if (!parsePerfStatsFlag (aSubValue, toReset, aFlagsRem, aFlagsAdd))
11078       {
11079         return Standard_False;
11080       }
11081     }
11082     aValue = aValue.SubString (aSplitPos + 1, aValue.Length());
11083   }
11084 }
11085
11086 //=======================================================================
11087 //function : VRenderParams
11088 //purpose  : Enables/disables rendering features
11089 //=======================================================================
11090
11091 static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
11092                                        Standard_Integer  theArgNb,
11093                                        const char**      theArgVec)
11094 {
11095   Handle(V3d_View) aView = ViewerTest::CurrentView();
11096   if (aView.IsNull())
11097   {
11098     std::cerr << "Error: no active viewer!\n";
11099     return 1;
11100   }
11101
11102   Graphic3d_RenderingParams& aParams = aView->ChangeRenderingParams();
11103   TCollection_AsciiString aCmdName (theArgVec[0]);
11104   aCmdName.LowerCase();
11105   if (aCmdName == "vraytrace")
11106   {
11107     if (theArgNb == 1)
11108     {
11109       theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "on" : "off") << " ";
11110       return 0;
11111     }
11112     else if (theArgNb == 2)
11113     {
11114       TCollection_AsciiString aValue (theArgVec[1]);
11115       aValue.LowerCase();
11116       if (aValue == "on"
11117        || aValue == "1")
11118       {
11119         aParams.Method = Graphic3d_RM_RAYTRACING;
11120         aView->Redraw();
11121         return 0;
11122       }
11123       else if (aValue == "off"
11124             || aValue == "0")
11125       {
11126         aParams.Method = Graphic3d_RM_RASTERIZATION;
11127         aView->Redraw();
11128         return 0;
11129       }
11130       else
11131       {
11132         std::cout << "Error: unknown argument '" << theArgVec[1] << "'\n";
11133         return 1;
11134       }
11135     }
11136     else
11137     {
11138       std::cout << "Error: wrong number of arguments\n";
11139       return 1;
11140     }
11141   }
11142
11143   if (theArgNb < 2)
11144   {
11145     theDI << "renderMode:  ";
11146     switch (aParams.Method)
11147     {
11148       case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11149       case Graphic3d_RM_RAYTRACING:    theDI << "raytrace ";      break;
11150     }
11151     theDI << "\n";
11152     theDI << "transparency:  ";
11153     switch (aParams.TransparencyMethod)
11154     {
11155       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
11156       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
11157                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
11158     }
11159     theDI << "\n";
11160     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
11161     theDI << "rendScale:      " <<  aParams.RenderResolutionScale                       << "\n";
11162     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
11163     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
11164     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
11165     theDI << "reflections:    " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
11166     theDI << "gleam:          " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
11167     theDI << "GI:             " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
11168     theDI << "blocked RNG:    " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
11169     theDI << "iss:            " << (aParams.AdaptiveScreenSampling      ? "on" : "off") << "\n";
11170     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
11171     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
11172     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
11173     theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
11174     theDI << "tile size (iss):" <<  aParams.RayTracingTileSize << "x" << aParams.RayTracingTileSize << "\n";
11175     theDI << "shadingModel: ";
11176     switch (aView->ShadingModel())
11177     {
11178       case Graphic3d_TOSM_DEFAULT:  theDI << "default"; break;
11179       case Graphic3d_TOSM_UNLIT:    theDI << "unlit";   break;
11180       case Graphic3d_TOSM_FACET:    theDI << "flat";    break;
11181       case Graphic3d_TOSM_VERTEX:   theDI << "gouraud"; break;
11182       case Graphic3d_TOSM_FRAGMENT: theDI << "phong";   break;
11183     }
11184     {
11185       theDI << "perfCounters:";
11186       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameRate) != 0)
11187       {
11188         theDI << " fps";
11189       }
11190       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_CPU) != 0)
11191       {
11192         theDI << " cpu";
11193       }
11194       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Structures) != 0)
11195       {
11196         theDI << " structs";
11197       }
11198       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Groups) != 0)
11199       {
11200         theDI << " groups";
11201       }
11202       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_GroupArrays) != 0)
11203       {
11204         theDI << " arrays";
11205       }
11206       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Triangles) != 0)
11207       {
11208         theDI << " tris";
11209       }
11210       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_Points) != 0)
11211       {
11212         theDI << " pnts";
11213       }
11214       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_EstimMem) != 0)
11215       {
11216         theDI << " gpumem";
11217       }
11218       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_FrameTime) != 0)
11219       {
11220         theDI << " frameTime";
11221       }
11222       if ((aParams.CollectedStats & Graphic3d_RenderingParams::PerfCounters_SkipImmediate) != 0)
11223       {
11224         theDI << " skipimmediate";
11225       }
11226       if (aParams.CollectedStats == Graphic3d_RenderingParams::PerfCounters_NONE)
11227       {
11228         theDI << " none";
11229       }
11230       theDI << "\n";
11231     }
11232     theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass        ? "on" : "off") << "\n";
11233     theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage  ? "on" : "off") << "\n";
11234     theDI << "frustum culling: " << (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On  ? "on" :
11235                                      aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off ? "off" :
11236                                                                                                                     "noUpdate") << "\n";
11237     theDI << "\n";
11238     return 0;
11239   }
11240
11241   Standard_Boolean toPrint = Standard_False;
11242   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
11243   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
11244   {
11245     Standard_CString        anArg (theArgVec[anArgIter]);
11246     TCollection_AsciiString aFlag (anArg);
11247     aFlag.LowerCase();
11248     if (anUpdateTool.parseRedrawMode (aFlag))
11249     {
11250       continue;
11251     }
11252     else if (aFlag == "-echo"
11253           || aFlag == "-print")
11254     {
11255       toPrint = Standard_True;
11256       anUpdateTool.Invalidate();
11257     }
11258     else if (aFlag == "-mode"
11259           || aFlag == "-rendermode"
11260           || aFlag == "-render_mode")
11261     {
11262       if (toPrint)
11263       {
11264         switch (aParams.Method)
11265         {
11266           case Graphic3d_RM_RASTERIZATION: theDI << "rasterization "; break;
11267           case Graphic3d_RM_RAYTRACING:    theDI << "ray-tracing ";   break;
11268         }
11269         continue;
11270       }
11271       else
11272       {
11273         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11274         return 1;
11275       }
11276     }
11277     else if (aFlag == "-ray"
11278           || aFlag == "-raytrace")
11279     {
11280       if (toPrint)
11281       {
11282         theDI << (aParams.Method == Graphic3d_RM_RAYTRACING ? "true" : "false") << " ";
11283         continue;
11284       }
11285
11286       aParams.Method = Graphic3d_RM_RAYTRACING;
11287     }
11288     else if (aFlag == "-rast"
11289           || aFlag == "-raster"
11290           || aFlag == "-rasterization")
11291     {
11292       if (toPrint)
11293       {
11294         theDI << (aParams.Method == Graphic3d_RM_RASTERIZATION ? "true" : "false") << " ";
11295         continue;
11296       }
11297
11298       aParams.Method = Graphic3d_RM_RASTERIZATION;
11299     }
11300     else if (aFlag == "-msaa")
11301     {
11302       if (toPrint)
11303       {
11304         theDI << aParams.NbMsaaSamples << " ";
11305         continue;
11306       }
11307       else if (++anArgIter >= theArgNb)
11308       {
11309         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11310         return 1;
11311       }
11312
11313       const Standard_Integer aNbSamples = Draw::Atoi (theArgVec[anArgIter]);
11314       if (aNbSamples < 0)
11315       {
11316         std::cerr << "Error: invalid number of MSAA samples " << aNbSamples << ".\n";
11317         return 1;
11318       }
11319       else
11320       {
11321         aParams.NbMsaaSamples = aNbSamples;
11322       }
11323     }
11324     else if (aFlag == "-linefeather"
11325           || aFlag == "-edgefeather"
11326           || aFlag == "-feather")
11327     {
11328       if (toPrint)
11329       {
11330         theDI << " " << aParams.LineFeather << " ";
11331         continue;
11332       }
11333       else if (++anArgIter >= theArgNb)
11334       {
11335         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11336         return 1;
11337       }
11338
11339       TCollection_AsciiString aParam = theArgVec[anArgIter];
11340       const Standard_ShortReal aFeather = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11341       if (aFeather <= 0.0f)
11342       {
11343         std::cerr << "Error: invalid value of line width feather " << aFeather << ". Should be > 0\n";
11344         return 1;
11345       }
11346       aParams.LineFeather = aFeather;
11347     }
11348     else if (aFlag == "-oit")
11349     {
11350       if (toPrint)
11351       {
11352         if (aParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
11353         {
11354           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
11355         }
11356         else
11357         {
11358           theDI << "off" << " ";
11359         }
11360         continue;
11361       }
11362       else if (++anArgIter >= theArgNb)
11363       {
11364         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11365         return 1;
11366       }
11367
11368       TCollection_AsciiString aParam = theArgVec[anArgIter];
11369       aParam.LowerCase();
11370       if (aParam.IsRealValue())
11371       {
11372         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
11373         if (aWeight < 0.f || aWeight > 1.f)
11374         {
11375           std::cerr << "Error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]\n";
11376           return 1;
11377         }
11378
11379         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
11380         aParams.OitDepthFactor     = aWeight;
11381       }
11382       else if (aParam == "off")
11383       {
11384         aParams.TransparencyMethod = Graphic3d_RTM_BLEND_UNORDERED;
11385       }
11386       else
11387       {
11388         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11389         return 1;
11390       }
11391     }
11392     else if (aFlag == "-depthprepass")
11393     {
11394       if (toPrint)
11395       {
11396         theDI << (aParams.ToEnableDepthPrepass ? "on " : "off ");
11397         continue;
11398       }
11399       aParams.ToEnableDepthPrepass = Standard_True;
11400       if (anArgIter + 1 < theArgNb
11401        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableDepthPrepass))
11402       {
11403         ++anArgIter;
11404       }
11405     }
11406     else if (aFlag == "-samplealphatocoverage"
11407           || aFlag == "-alphatocoverage")
11408     {
11409       if (toPrint)
11410       {
11411         theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off ");
11412         continue;
11413       }
11414       aParams.ToEnableAlphaToCoverage = Standard_True;
11415       if (anArgIter + 1 < theArgNb
11416        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage))
11417       {
11418         ++anArgIter;
11419       }
11420     }
11421     else if (aFlag == "-rendscale"
11422           || aFlag == "-renderscale"
11423           || aFlag == "-renderresolutionscale")
11424     {
11425       if (toPrint)
11426       {
11427         theDI << aParams.RenderResolutionScale << " ";
11428         continue;
11429       }
11430       else if (++anArgIter >= theArgNb)
11431       {
11432         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11433         return 1;
11434       }
11435
11436       const Standard_Real aScale = Draw::Atof (theArgVec[anArgIter]);
11437       if (aScale < 0.01)
11438       {
11439         std::cerr << "Error: invalid rendering resolution scale " << aScale << ".\n";
11440         return 1;
11441       }
11442       else
11443       {
11444         aParams.RenderResolutionScale = Standard_ShortReal(aScale);
11445       }
11446     }
11447     else if (aFlag == "-raydepth"
11448           || aFlag == "-ray_depth")
11449     {
11450       if (toPrint)
11451       {
11452         theDI << aParams.RaytracingDepth << " ";
11453         continue;
11454       }
11455       else if (++anArgIter >= theArgNb)
11456       {
11457         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11458         return 1;
11459       }
11460
11461       const Standard_Integer aDepth = Draw::Atoi (theArgVec[anArgIter]);
11462
11463       // We allow RaytracingDepth be more than 10 in case of GI enabled
11464       if (aDepth < 1 || (aDepth > 10 && !aParams.IsGlobalIlluminationEnabled))
11465       {
11466         std::cerr << "Error: invalid ray-tracing depth " << aDepth << ". Should be within range [1; 10]\n";
11467         return 1;
11468       }
11469       else
11470       {
11471         aParams.RaytracingDepth = aDepth;
11472       }
11473     }
11474     else if (aFlag == "-shad"
11475           || aFlag == "-shadows")
11476     {
11477       if (toPrint)
11478       {
11479         theDI << (aParams.IsShadowEnabled ? "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.IsShadowEnabled = toEnable;
11490     }
11491     else if (aFlag == "-refl"
11492           || aFlag == "-reflections")
11493     {
11494       if (toPrint)
11495       {
11496         theDI << (aParams.IsReflectionEnabled ? "on" : "off") << " ";
11497         continue;
11498       }
11499
11500       Standard_Boolean toEnable = Standard_True;
11501       if (++anArgIter < theArgNb
11502       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11503       {
11504         --anArgIter;
11505       }
11506       aParams.IsReflectionEnabled = toEnable;
11507     }
11508     else if (aFlag == "-fsaa")
11509     {
11510       if (toPrint)
11511       {
11512         theDI << (aParams.IsAntialiasingEnabled ? "on" : "off") << " ";
11513         continue;
11514       }
11515
11516       Standard_Boolean toEnable = Standard_True;
11517       if (++anArgIter < theArgNb
11518       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11519       {
11520         --anArgIter;
11521       }
11522       aParams.IsAntialiasingEnabled = toEnable;
11523     }
11524     else if (aFlag == "-gleam")
11525     {
11526       if (toPrint)
11527       {
11528         theDI << (aParams.IsTransparentShadowEnabled ? "on" : "off") << " ";
11529         continue;
11530       }
11531
11532       Standard_Boolean toEnable = Standard_True;
11533       if (++anArgIter < theArgNb
11534       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11535       {
11536         --anArgIter;
11537       }
11538       aParams.IsTransparentShadowEnabled = toEnable;
11539     }
11540     else if (aFlag == "-gi")
11541     {
11542       if (toPrint)
11543       {
11544         theDI << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << " ";
11545         continue;
11546       }
11547
11548       Standard_Boolean toEnable = Standard_True;
11549       if (++anArgIter < theArgNb
11550       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11551       {
11552         --anArgIter;
11553       }
11554       aParams.IsGlobalIlluminationEnabled = toEnable;
11555       if (!toEnable)
11556       {
11557         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
11558       }
11559     }
11560     else if (aFlag == "-blockedrng"
11561           || aFlag == "-brng")
11562     {
11563       if (toPrint)
11564       {
11565         theDI << (aParams.CoherentPathTracingMode ? "on" : "off") << " ";
11566         continue;
11567       }
11568
11569       Standard_Boolean toEnable = Standard_True;
11570       if (++anArgIter < theArgNb
11571         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11572       {
11573         --anArgIter;
11574       }
11575       aParams.CoherentPathTracingMode = toEnable;
11576     }
11577     else if (aFlag == "-maxrad")
11578     {
11579       if (toPrint)
11580       {
11581         theDI << aParams.RadianceClampingValue << " ";
11582         continue;
11583       }
11584       else if (++anArgIter >= theArgNb)
11585       {
11586         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11587         return 1;
11588       }
11589
11590       const TCollection_AsciiString aMaxRadStr = theArgVec[anArgIter];
11591       if (!aMaxRadStr.IsRealValue())
11592       {
11593         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11594         return 1;
11595       }
11596
11597       const Standard_Real aMaxRadiance = aMaxRadStr.RealValue();
11598       if (aMaxRadiance <= 0.0)
11599       {
11600         std::cerr << "Error: invalid radiance clamping value " << aMaxRadiance << ".\n";
11601         return 1;
11602       }
11603       else
11604       {
11605         aParams.RadianceClampingValue = static_cast<Standard_ShortReal> (aMaxRadiance);
11606       }
11607     }
11608     else if (aFlag == "-iss")
11609     {
11610       if (toPrint)
11611       {
11612         theDI << (aParams.AdaptiveScreenSampling ? "on" : "off") << " ";
11613         continue;
11614       }
11615
11616       Standard_Boolean toEnable = Standard_True;
11617       if (++anArgIter < theArgNb
11618         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11619       {
11620         --anArgIter;
11621       }
11622       aParams.AdaptiveScreenSampling = toEnable;
11623     }
11624     else if (aFlag == "-issatomic")
11625     {
11626       if (toPrint)
11627       {
11628         theDI << (aParams.AdaptiveScreenSamplingAtomic ? "on" : "off") << " ";
11629         continue;
11630       }
11631
11632       Standard_Boolean toEnable = Standard_True;
11633       if (++anArgIter < theArgNb
11634       && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11635       {
11636         --anArgIter;
11637       }
11638       aParams.AdaptiveScreenSamplingAtomic = toEnable;
11639     }
11640     else if (aFlag == "-issd")
11641     {
11642       if (toPrint)
11643       {
11644         theDI << (aParams.ShowSamplingTiles ? "on" : "off") << " ";
11645         continue;
11646       }
11647
11648       Standard_Boolean toEnable = Standard_True;
11649       if (++anArgIter < theArgNb
11650         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11651       {
11652         --anArgIter;
11653       }
11654       aParams.ShowSamplingTiles = toEnable;
11655     }
11656     else if (aFlag == "-tilesize")
11657     {
11658       if (toPrint)
11659       {
11660         theDI << aParams.RayTracingTileSize << " ";
11661         continue;
11662       }
11663       else if (++anArgIter >= theArgNb)
11664       {
11665         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11666         return 1;
11667       }
11668
11669       const Standard_Integer aTileSize = Draw::Atoi (theArgVec[anArgIter]);
11670       if (aTileSize < 1)
11671       {
11672         std::cerr << "Error: invalid size of ISS tile " << aTileSize << ".\n";
11673         return 1;
11674       }
11675       aParams.RayTracingTileSize = aTileSize;
11676     }
11677     else if (aFlag == "-nbtiles")
11678     {
11679       if (toPrint)
11680       {
11681         theDI << aParams.NbRayTracingTiles << " ";
11682         continue;
11683       }
11684       else if (++anArgIter >= theArgNb)
11685       {
11686         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11687         return 1;
11688       }
11689
11690       const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
11691       if (aNbTiles < -1)
11692       {
11693         std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
11694         return 1;
11695       }
11696       else if (aNbTiles > 0
11697             && (aNbTiles < 64
11698              || aNbTiles > 1024))
11699       {
11700         std::cerr << "Warning: suboptimal number of ISS tiles " << aNbTiles << ". Recommended range: [64, 1024].\n";
11701       }
11702       aParams.NbRayTracingTiles = aNbTiles;
11703     }
11704     else if (aFlag == "-env")
11705     {
11706       if (toPrint)
11707       {
11708         theDI << (aParams.UseEnvironmentMapBackground ? "on" : "off") << " ";
11709         continue;
11710       }
11711
11712       Standard_Boolean toEnable = Standard_True;
11713       if (++anArgIter < theArgNb
11714         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11715       {
11716         --anArgIter;
11717       }
11718       aParams.UseEnvironmentMapBackground = toEnable;
11719     }
11720     else if (aFlag == "-twoside")
11721     {
11722       if (toPrint)
11723       {
11724         theDI << (aParams.TwoSidedBsdfModels ? "on" : "off") << " ";
11725         continue;
11726       }
11727
11728       Standard_Boolean toEnable = Standard_True;
11729       if (++anArgIter < theArgNb
11730         && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11731       {
11732         --anArgIter;
11733       }
11734       aParams.TwoSidedBsdfModels = toEnable;
11735     }
11736     else if (aFlag == "-shademodel"
11737           || aFlag == "-shadingmodel"
11738           || aFlag == "-shading")
11739     {
11740       if (toPrint)
11741       {
11742         switch (aView->ShadingModel())
11743         {
11744           case Graphic3d_TOSM_DEFAULT:  theDI << "default";  break;
11745           case Graphic3d_TOSM_UNLIT:    theDI << "unlit ";   break;
11746           case Graphic3d_TOSM_FACET:    theDI << "flat ";    break;
11747           case Graphic3d_TOSM_VERTEX:   theDI << "gouraud "; break;
11748           case Graphic3d_TOSM_FRAGMENT: theDI << "phong ";   break;
11749         }
11750         continue;
11751       }
11752
11753       if (++anArgIter >= theArgNb)
11754       {
11755         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11756       }
11757
11758       Graphic3d_TypeOfShadingModel aModel = Graphic3d_TOSM_DEFAULT;
11759       if (ViewerTest::ParseShadingModel (theArgVec[anArgIter], aModel)
11760        && aModel != Graphic3d_TOSM_DEFAULT)
11761       {
11762         aView->SetShadingModel (aModel);
11763       }
11764       else
11765       {
11766         std::cout << "Error: unknown shading model '" << theArgVec[anArgIter] << "'\n";
11767         return 1;
11768       }
11769     }
11770     else if (aFlag == "-resolution")
11771     {
11772       if (++anArgIter >= theArgNb)
11773       {
11774         std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
11775         return 1;
11776       }
11777
11778       TCollection_AsciiString aResolution (theArgVec[anArgIter]);
11779       if (aResolution.IsIntegerValue())
11780       {
11781         aView->ChangeRenderingParams().Resolution = static_cast<unsigned int> (Draw::Atoi (aResolution.ToCString()));
11782       }
11783       else
11784       {
11785         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11786         return 1;
11787       }
11788     }
11789     else if (aFlag == "-rebuildglsl"
11790           || aFlag == "-rebuild")
11791     {
11792       if (toPrint)
11793       {
11794         theDI << (aParams.RebuildRayTracingShaders ? "on" : "off") << " ";
11795         continue;
11796       }
11797
11798       Standard_Boolean toEnable = Standard_True;
11799       if (++anArgIter < theArgNb
11800           && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
11801       {
11802         --anArgIter;
11803       }
11804       aParams.RebuildRayTracingShaders = toEnable;
11805     }
11806     else if (aFlag == "-focal")
11807     {
11808       if (++anArgIter >= theArgNb)
11809       {
11810         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11811         return 1;
11812       }
11813
11814       TCollection_AsciiString aParam (theArgVec[anArgIter]);
11815       if (aParam.IsRealValue())
11816       {
11817         float aFocalDist = static_cast<float> (aParam.RealValue());
11818         if (aFocalDist < 0)
11819         {
11820           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11821           return 1;
11822         }
11823         aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
11824       }
11825       else
11826       {
11827         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11828         return 1;
11829       }
11830     }
11831     else if (aFlag == "-aperture")
11832     {
11833       if (++anArgIter >= theArgNb)
11834       {
11835         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11836         return 1;
11837       }
11838
11839       TCollection_AsciiString aParam(theArgVec[anArgIter]);
11840       if (aParam.IsRealValue())
11841       {
11842         float aApertureSize = static_cast<float> (aParam.RealValue());
11843         if (aApertureSize < 0)
11844         {
11845           std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
11846           return 1;
11847         }
11848         aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
11849       }
11850       else
11851       {
11852         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11853         return 1;
11854       }
11855     }
11856     else if (aFlag == "-exposure")
11857     {
11858       if (++anArgIter >= theArgNb)
11859       {
11860         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11861         return 1;
11862       }
11863
11864       TCollection_AsciiString anExposure (theArgVec[anArgIter]);
11865       if (anExposure.IsRealValue())
11866       {
11867         aView->ChangeRenderingParams().Exposure = static_cast<float> (anExposure.RealValue());
11868       }
11869       else
11870       {
11871         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11872         return 1;
11873       }
11874     }
11875     else if (aFlag == "-whitepoint")
11876     {
11877       if (++anArgIter >= theArgNb)
11878       {
11879         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11880         return 1;
11881       }
11882
11883       TCollection_AsciiString aWhitePoint (theArgVec[anArgIter]);
11884       if (aWhitePoint.IsRealValue())
11885       {
11886         aView->ChangeRenderingParams().WhitePoint = static_cast<float> (aWhitePoint.RealValue());
11887       }
11888       else
11889       {
11890         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11891         return 1;
11892       }
11893     }
11894     else if (aFlag == "-tonemapping")
11895     {
11896       if (++anArgIter >= theArgNb)
11897       {
11898         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11899         return 1;
11900       }
11901
11902       TCollection_AsciiString aMode (theArgVec[anArgIter]);
11903       aMode.LowerCase();
11904
11905       if (aMode == "disabled")
11906       {
11907         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Disabled;
11908       }
11909       else if (aMode == "filmic")
11910       {
11911         aView->ChangeRenderingParams().ToneMappingMethod = Graphic3d_ToneMappingMethod_Filmic;
11912       }
11913       else
11914       {
11915         std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
11916         return 1;
11917       }
11918     }
11919     else if (aFlag == "-performancestats"
11920           || aFlag == "-performancecounters"
11921           || aFlag == "-perfstats"
11922           || aFlag == "-perfcounters"
11923           || aFlag == "-stats")
11924     {
11925       if (++anArgIter >= theArgNb)
11926       {
11927         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11928         return 1;
11929       }
11930
11931       TCollection_AsciiString aFlagsStr (theArgVec[anArgIter]);
11932       aFlagsStr.LowerCase();
11933       Graphic3d_RenderingParams::PerfCounters aFlags = aView->ChangeRenderingParams().CollectedStats;
11934       if (!convertToPerfStatsFlags (aFlagsStr, aFlags))
11935       {
11936         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11937         return 1;
11938       }
11939       aView->ChangeRenderingParams().CollectedStats = aFlags;
11940       aView->ChangeRenderingParams().ToShowStats = aFlags != Graphic3d_RenderingParams::PerfCounters_NONE;
11941     }
11942     else if (aFlag == "-perfupdateinterval"
11943           || aFlag == "-statsupdateinterval")
11944     {
11945       if (++anArgIter >= theArgNb)
11946       {
11947         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11948         return 1;
11949       }
11950       aView->ChangeRenderingParams().StatsUpdateInterval = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11951     }
11952     else if (aFlag == "-perfchart"
11953           || aFlag == "-statschart")
11954     {
11955       if (++anArgIter >= theArgNb)
11956       {
11957         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11958         return 1;
11959       }
11960       aView->ChangeRenderingParams().StatsNbFrames = Draw::Atoi (theArgVec[anArgIter]);
11961     }
11962     else if (aFlag == "-perfchartmax"
11963           || aFlag == "-statschartmax")
11964     {
11965       if (++anArgIter >= theArgNb)
11966       {
11967         std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
11968         return 1;
11969       }
11970       aView->ChangeRenderingParams().StatsMaxChartTime = (Standard_ShortReal )Draw::Atof (theArgVec[anArgIter]);
11971     }
11972     else if (aFlag == "-frustumculling"
11973           || aFlag == "-culling")
11974     {
11975       if (toPrint)
11976       {
11977         theDI << ((aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_On)  ? "on" :
11978                   (aParams.FrustumCullingState == Graphic3d_RenderingParams::FrustumCulling_Off) ? "off" :
11979                                                                                                    "noUpdate") << " ";
11980         continue;
11981       }
11982
11983       Graphic3d_RenderingParams::FrustumCulling aState = Graphic3d_RenderingParams::FrustumCulling_On;
11984       if (++anArgIter < theArgNb)
11985       {
11986         TCollection_AsciiString aStateStr(theArgVec[anArgIter]);
11987         aStateStr.LowerCase();
11988         bool toEnable = true;
11989         if (ViewerTest::ParseOnOff (aStateStr.ToCString(), toEnable))
11990         {
11991           aState = toEnable ? Graphic3d_RenderingParams::FrustumCulling_On : Graphic3d_RenderingParams::FrustumCulling_Off;
11992         }
11993         else if (aStateStr == "noupdate"
11994               || aStateStr == "freeze")
11995         {
11996           aState = Graphic3d_RenderingParams::FrustumCulling_NoUpdate;
11997         }
11998         else
11999         {
12000           --anArgIter;
12001         }
12002       }
12003       aParams.FrustumCullingState = aState;
12004     }
12005     else
12006     {
12007       std::cout << "Error: wrong syntax, unknown flag '" << anArg << "'\n";
12008       return 1;
12009     }
12010   }
12011
12012   return 0;
12013 }
12014
12015 //=======================================================================
12016 //function : searchInfo
12017 //purpose  :
12018 //=======================================================================
12019 inline TCollection_AsciiString searchInfo (const TColStd_IndexedDataMapOfStringString& theDict,
12020                                            const TCollection_AsciiString&              theKey)
12021 {
12022   for (TColStd_IndexedDataMapOfStringString::Iterator anIter (theDict); anIter.More(); anIter.Next())
12023   {
12024     if (TCollection_AsciiString::IsSameString (anIter.Key(), theKey, Standard_False))
12025     {
12026       return anIter.Value();
12027     }
12028   }
12029   return TCollection_AsciiString();
12030 }
12031
12032 //=======================================================================
12033 //function : VStatProfiler
12034 //purpose  :
12035 //=======================================================================
12036 static Standard_Integer VStatProfiler (Draw_Interpretor& theDI,
12037                                        Standard_Integer  theArgNb,
12038                                        const char**      theArgVec)
12039 {
12040   Handle(V3d_View) aView = ViewerTest::CurrentView();
12041   if (aView.IsNull())
12042   {
12043     std::cerr << "Error: no active viewer!\n";
12044     return 1;
12045   }
12046
12047   Standard_Boolean toRedraw = Standard_True;
12048   Graphic3d_RenderingParams::PerfCounters aPrevCounters = aView->ChangeRenderingParams().CollectedStats;
12049   Standard_ShortReal aPrevUpdInterval = aView->ChangeRenderingParams().StatsUpdateInterval;
12050   Graphic3d_RenderingParams::PerfCounters aRenderParams = Graphic3d_RenderingParams::PerfCounters_NONE;
12051   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12052   {
12053     Standard_CString        anArg (theArgVec[anArgIter]);
12054     TCollection_AsciiString aFlag (anArg);
12055     aFlag.LowerCase();
12056     if (aFlag == "-noredraw")
12057     {
12058       toRedraw = Standard_False;
12059     }
12060     else
12061     {
12062       Graphic3d_RenderingParams::PerfCounters aParam = Graphic3d_RenderingParams::PerfCounters_NONE;
12063       if      (aFlag == "fps")        aParam = Graphic3d_RenderingParams::PerfCounters_FrameRate;
12064       else if (aFlag == "cpu")        aParam = Graphic3d_RenderingParams::PerfCounters_CPU;
12065       else if (aFlag == "alllayers"
12066             || aFlag == "layers")     aParam = Graphic3d_RenderingParams::PerfCounters_Layers;
12067       else if (aFlag == "allstructs"
12068             || aFlag == "structs")    aParam = Graphic3d_RenderingParams::PerfCounters_Structures;
12069       else if (aFlag == "groups")     aParam = Graphic3d_RenderingParams::PerfCounters_Groups;
12070       else if (aFlag == "allarrays"
12071             || aFlag == "fillarrays"
12072             || aFlag == "linearrays"
12073             || aFlag == "pointarrays"
12074             || aFlag == "textarrays") aParam = Graphic3d_RenderingParams::PerfCounters_GroupArrays;
12075       else if (aFlag == "triangles")  aParam = Graphic3d_RenderingParams::PerfCounters_Triangles;
12076       else if (aFlag == "points")     aParam = Graphic3d_RenderingParams::PerfCounters_Points;
12077       else if (aFlag == "geommem"
12078             || aFlag == "texturemem"
12079             || aFlag == "framemem")   aParam = Graphic3d_RenderingParams::PerfCounters_EstimMem;
12080       else if (aFlag == "elapsedframe"
12081             || aFlag == "cpuframeaverage"
12082             || aFlag == "cpupickingaverage"
12083             || aFlag == "cpucullingaverage"
12084             || aFlag == "cpudynaverage"
12085             || aFlag == "cpuframemax"
12086             || aFlag == "cpupickingmax"
12087             || aFlag == "cpucullingmax"
12088             || aFlag == "cpudynmax")  aParam = Graphic3d_RenderingParams::PerfCounters_FrameTime;
12089       else
12090       {
12091         std::cerr << "Unknown argument '" << theArgVec[anArgIter] << "'!\n";
12092         continue;
12093       }
12094
12095       aRenderParams = Graphic3d_RenderingParams::PerfCounters (aRenderParams | aParam);
12096     }
12097   }
12098
12099   if (aRenderParams != Graphic3d_RenderingParams::PerfCounters_NONE)
12100   {
12101     aView->ChangeRenderingParams().CollectedStats =
12102       Graphic3d_RenderingParams::PerfCounters (aView->RenderingParams().CollectedStats | aRenderParams);
12103
12104     if (toRedraw)
12105     {
12106       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12107       aView->Redraw();
12108       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12109     }
12110
12111     TColStd_IndexedDataMapOfStringString aDict;
12112     aView->StatisticInformation (aDict);
12113
12114     aView->ChangeRenderingParams().CollectedStats = aPrevCounters;
12115
12116     for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
12117     {
12118       Standard_CString        anArg(theArgVec[anArgIter]);
12119       TCollection_AsciiString aFlag(anArg);
12120       aFlag.LowerCase();
12121       if (aFlag == "fps")
12122       {
12123         theDI << searchInfo (aDict, "FPS") << " ";
12124       }
12125       else if (aFlag == "cpu")
12126       {
12127         theDI << searchInfo (aDict, "CPU FPS") << " ";
12128       }
12129       else if (aFlag == "alllayers")
12130       {
12131         theDI << searchInfo (aDict, "Layers") << " ";
12132       }
12133       else if (aFlag == "layers")
12134       {
12135         theDI << searchInfo (aDict, "Rendered layers") << " ";
12136       }
12137       else if (aFlag == "allstructs")
12138       {
12139         theDI << searchInfo (aDict, "Structs") << " ";
12140       }
12141       else if (aFlag == "structs")
12142       {
12143         theDI << searchInfo (aDict, "Rendered structs") << " ";
12144       }
12145       else if (aFlag == "groups")
12146       {
12147         theDI << searchInfo (aDict, "Rendered groups") << " ";
12148       }
12149       else if (aFlag == "allarrays")
12150       {
12151         theDI << searchInfo (aDict, "Rendered arrays") << " ";
12152       }
12153       else if (aFlag == "fillarrays")
12154       {
12155         theDI << searchInfo (aDict, "Rendered [fill] arrays") << " ";
12156       }
12157       else if (aFlag == "linearrays")
12158       {
12159         theDI << searchInfo (aDict, "Rendered [line] arrays") << " ";
12160       }
12161       else if (aFlag == "pointarrays")
12162       {
12163         theDI << searchInfo (aDict, "Rendered [point] arrays") << " ";
12164       }
12165       else if (aFlag == "textarrays")
12166       {
12167         theDI << searchInfo (aDict, "Rendered [text] arrays") << " ";
12168       }
12169       else if (aFlag == "triangles")
12170       {
12171         theDI << searchInfo (aDict, "Rendered triangles") << " ";
12172       }
12173       else if (aFlag == "points")
12174       {
12175         theDI << searchInfo (aDict, "Rendered points") << " ";
12176       }
12177       else if (aFlag == "geommem")
12178       {
12179         theDI << searchInfo (aDict, "GPU Memory [geometry]") << " ";
12180       }
12181       else if (aFlag == "texturemem")
12182       {
12183         theDI << searchInfo (aDict, "GPU Memory [textures]") << " ";
12184       }
12185       else if (aFlag == "framemem")
12186       {
12187         theDI << searchInfo (aDict, "GPU Memory [frames]") << " ";
12188       }
12189       else if (aFlag == "elapsedframe")
12190       {
12191         theDI << searchInfo (aDict, "Elapsed Frame (average)") << " ";
12192       }
12193       else if (aFlag == "cpuframe_average")
12194       {
12195         theDI << searchInfo (aDict, "CPU Frame (average)") << " ";
12196       }
12197       else if (aFlag == "cpupicking_average")
12198       {
12199         theDI << searchInfo (aDict, "CPU Picking (average)") << " ";
12200       }
12201       else if (aFlag == "cpuculling_average")
12202       {
12203         theDI << searchInfo (aDict, "CPU Culling (average)") << " ";
12204       }
12205       else if (aFlag == "cpudyn_average")
12206       {
12207         theDI << searchInfo (aDict, "CPU Dynamics (average)") << " ";
12208       }
12209       else if (aFlag == "cpuframe_max")
12210       {
12211         theDI << searchInfo (aDict, "CPU Frame (max)") << " ";
12212       }
12213       else if (aFlag == "cpupicking_max")
12214       {
12215         theDI << searchInfo (aDict, "CPU Picking (max)") << " ";
12216       }
12217       else if (aFlag == "cpuculling_max")
12218       {
12219         theDI << searchInfo (aDict, "CPU Culling (max)") << " ";
12220       }
12221       else if (aFlag == "cpudyn_max")
12222       {
12223         theDI << searchInfo (aDict, "CPU Dynamics (max)") << " ";
12224       }
12225     }
12226   }
12227   else
12228   {
12229     if (toRedraw)
12230     {
12231       aView->ChangeRenderingParams().StatsUpdateInterval = -1;
12232       aView->Redraw();
12233       aView->ChangeRenderingParams().StatsUpdateInterval = aPrevUpdInterval;
12234     }
12235     theDI << "Statistic info:\n" << aView->StatisticInformation();
12236   }
12237   return 0;
12238 }
12239
12240 //=======================================================================
12241 //function : VXRotate
12242 //purpose  :
12243 //=======================================================================
12244 static Standard_Integer VXRotate (Draw_Interpretor& di,
12245                                    Standard_Integer argc,
12246                                    const char ** argv)
12247 {
12248   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
12249   if (aContext.IsNull())
12250   {
12251     di << argv[0] << "ERROR : use 'vinit' command before \n";
12252     return 1;
12253   }
12254
12255   if (argc != 3)
12256   {
12257     di << "ERROR : Usage : " << argv[0] << " name angle\n";
12258     return 1;
12259   }
12260
12261   TCollection_AsciiString aName (argv[1]);
12262   Standard_Real anAngle = Draw::Atof (argv[2]);
12263
12264   // find object
12265   ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
12266   Handle(AIS_InteractiveObject) anIObj;
12267   if (!aMap.Find2 (aName, anIObj))
12268   {
12269     di << "Use 'vdisplay' before\n";
12270     return 1;
12271   }
12272
12273   gp_Trsf aTransform;
12274   aTransform.SetRotation (gp_Ax1 (gp_Pnt (0.0, 0.0, 0.0), gp_Vec (1.0, 0.0, 0.0)), anAngle);
12275   aTransform.SetTranslationPart (anIObj->LocalTransformation().TranslationPart());
12276
12277   aContext->SetLocation (anIObj, aTransform);
12278   aContext->UpdateCurrentViewer();
12279   return 0;
12280 }
12281
12282 //===============================================================================================
12283 //class   : ViewerTest_AISManipulator
12284 //purpose : Proxy class maintaining automated registry map to enlist existing AIS_Manipulator instances
12285 //===============================================================================================
12286 DEFINE_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12287
12288 class ViewerTest_AISManipulator : public AIS_Manipulator
12289 {
12290 public:
12291
12292   ViewerTest_AISManipulator() : AIS_Manipulator()
12293   {
12294     GetMapOfAISManipulators().Add (this);
12295   }
12296
12297   virtual ~ViewerTest_AISManipulator()
12298   {
12299     GetMapOfAISManipulators().Remove (this);
12300   }
12301
12302   DEFINE_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12303 };
12304
12305 IMPLEMENT_STANDARD_HANDLE (ViewerTest_AISManipulator, AIS_Manipulator)
12306 IMPLEMENT_STANDARD_RTTIEXT(ViewerTest_AISManipulator, AIS_Manipulator)
12307
12308 //===============================================================================================
12309 //function : VManipulator
12310 //purpose  :
12311 //===============================================================================================
12312 static int VManipulator (Draw_Interpretor& theDi,
12313                          Standard_Integer  theArgsNb,
12314                          const char**      theArgVec)
12315 {
12316   Handle(V3d_View)   aCurrentView   = ViewerTest::CurrentView();
12317   Handle(V3d_Viewer) aViewer = ViewerTest::GetViewerFromContext();
12318   ViewerTest::GetAISContext()->MainSelector()->SetPickClosest (Standard_False);
12319   if (aCurrentView.IsNull()
12320    || aViewer.IsNull())
12321   {
12322     std::cerr << "No active viewer!\n";
12323     return 1;
12324   }
12325
12326   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), ViewerTest::CurrentView());
12327   Standard_Integer anArgIter = 1;
12328   for (; anArgIter < theArgsNb; ++anArgIter)
12329   {
12330     anUpdateTool.parseRedrawMode (theArgVec[anArgIter]);
12331   }
12332
12333   ViewerTest_CmdParser aCmd;
12334   aCmd.SetDescription ("Manages manipulator for interactive objects:");
12335   aCmd.AddOption ("attach",         "... object - attach manipulator to an object");
12336   aCmd.AddOption ("adjustPosition", "... {0|1} - adjust position when attaching");
12337   aCmd.AddOption ("adjustSize",     "... {0|1} - adjust size when attaching ");
12338   aCmd.AddOption ("enableModes",    "... {0|1} - enable modes when attaching ");
12339   aCmd.AddOption ("view",           "... {active | [view name]} - define view in which manipulator will be displayed, 'all' by default");
12340   aCmd.AddOption ("detach",         "...       - detach manipulator");
12341
12342   aCmd.AddOption ("startTransform",   "... mouse_x mouse_y - invoke start transformation");
12343   aCmd.AddOption ("transform",        "... mouse_x mouse_y - invoke transformation");
12344   aCmd.AddOption ("stopTransform",    "... [abort] - invoke stop transformation");
12345
12346   aCmd.AddOption ("move",   "... x y z - move object");
12347   aCmd.AddOption ("rotate", "... x y z dx dy dz angle - rotate object");
12348   aCmd.AddOption ("scale",  "... factor - scale object");
12349
12350   aCmd.AddOption ("autoActivate",      "... {0|1} - set activation on detection");
12351   aCmd.AddOption ("followTranslation", "... {0|1} - set following translation transform");
12352   aCmd.AddOption ("followRotation",    "... {0|1} - set following rotation transform");
12353   aCmd.AddOption ("followDragging",    "... {0|1} - set following dragging transform");
12354   aCmd.AddOption ("gap",               "... value - set gap between sub-parts");
12355   aCmd.AddOption ("part",              "... axis mode {0|1} - set visual part");
12356   aCmd.AddOption ("parts",             "... all axes mode {0|1} - set visual part");
12357   aCmd.AddOption ("pos",               "... x y z [nx ny nz [xx xy xz]] - set position of manipulator");
12358   aCmd.AddOption ("size",              "... size - set size of manipulator");
12359   aCmd.AddOption ("zoomable",          "... {0|1} - set zoom persistence");
12360
12361   aCmd.Parse (theArgsNb, theArgVec);
12362
12363   if (aCmd.HasOption ("help"))
12364   {
12365     theDi.PrintHelp (theArgVec[0]);
12366     return 0;
12367   }
12368
12369   ViewerTest_DoubleMapOfInteractiveAndName& aMapAIS = GetMapOfAIS();
12370
12371   TCollection_AsciiString aName (aCmd.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0).c_str());
12372
12373   if (aName.IsEmpty())
12374   {
12375     std::cerr << theArgVec[0] << " error: please specify AIS manipulator's name as the first argument.\n";
12376     return 1;
12377   }
12378
12379   // ----------------------------------
12380   // detach existing manipulator object
12381   // ----------------------------------
12382
12383   if (aCmd.HasOption ("detach"))
12384   {
12385     if (!aMapAIS.IsBound2 (aName))
12386     {
12387       std::cerr << theArgVec[0] << " error: could not find \"" << aName << "\" AIS object.\n";
12388       return 1;
12389     }
12390
12391     Handle(AIS_Manipulator) aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12392     if (aManipulator.IsNull())
12393     {
12394       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12395       return 1;
12396     }
12397
12398     aManipulator->Detach();
12399     aMapAIS.UnBind2 (aName);
12400     ViewerTest::GetAISContext()->Remove (aManipulator, Standard_True);
12401
12402     return 0;
12403   }
12404
12405   // -----------------------------------------------
12406   // find or create manipulator if it does not exist
12407   // -----------------------------------------------
12408
12409   Handle(AIS_Manipulator) aManipulator;
12410   if (!aMapAIS.IsBound2 (aName))
12411   {
12412     std::cout << theArgVec[0] << ": AIS object \"" << aName << "\" has been created.\n";
12413
12414     aManipulator = new ViewerTest_AISManipulator();
12415     aManipulator->SetModeActivationOnDetection (true);
12416     aMapAIS.Bind (aManipulator, aName);
12417   }
12418   else
12419   {
12420     aManipulator = Handle(AIS_Manipulator)::DownCast (aMapAIS.Find2 (aName));
12421     if (aManipulator.IsNull())
12422     {
12423       std::cerr << theArgVec[0] << " error: \"" << aName << "\" is not an AIS manipulator.\n";
12424       return 1;
12425     }
12426   }
12427
12428   // -----------------------------------------
12429   // change properties of manipulator instance
12430   // -----------------------------------------
12431
12432   if (aCmd.HasOption ("autoActivate", 1, Standard_True))
12433   {
12434     aManipulator->SetModeActivationOnDetection (aCmd.ArgBool ("autoActivate"));
12435   }
12436   if (aCmd.HasOption ("followTranslation", 1, Standard_True))
12437   {
12438     aManipulator->ChangeTransformBehavior().SetFollowTranslation (aCmd.ArgBool ("followTranslation"));
12439   }
12440   if (aCmd.HasOption ("followRotation", 1, Standard_True))
12441   {
12442     aManipulator->ChangeTransformBehavior().SetFollowRotation (aCmd.ArgBool ("followRotation"));
12443   }
12444   if (aCmd.HasOption("followDragging", 1, Standard_True))
12445   {
12446     aManipulator->ChangeTransformBehavior().SetFollowDragging(aCmd.ArgBool("followDragging"));
12447   }
12448   if (aCmd.HasOption ("gap", 1, Standard_True))
12449   {
12450     aManipulator->SetGap (aCmd.ArgFloat ("gap"));
12451   }
12452   if (aCmd.HasOption ("part", 3, Standard_True))
12453   {
12454     Standard_Integer anAxis = aCmd.ArgInt  ("part", 0);
12455     Standard_Integer aMode  = aCmd.ArgInt  ("part", 1);
12456     Standard_Boolean aOnOff = aCmd.ArgBool ("part", 2);
12457     if (aMode < 1 || aMode > 4)
12458     {
12459       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12460       return 1;
12461     }
12462
12463     aManipulator->SetPart (anAxis, static_cast<AIS_ManipulatorMode> (aMode), aOnOff);
12464   }
12465   if (aCmd.HasOption("parts", 2, Standard_True))
12466   {
12467     Standard_Integer aMode = aCmd.ArgInt("parts", 0);
12468     Standard_Boolean aOnOff = aCmd.ArgBool("parts", 1);
12469     if (aMode < 1 || aMode > 4)
12470     {
12471       std::cerr << theArgVec[0] << " error: mode value should be in range [1, 4].\n";
12472       return 1;
12473     }
12474
12475     aManipulator->SetPart(static_cast<AIS_ManipulatorMode>(aMode), aOnOff);
12476   }
12477   if (aCmd.HasOption ("pos", 3, Standard_True))
12478   {
12479     gp_Pnt aLocation = aCmd.ArgPnt ("pos", 0);
12480     gp_Dir aVDir     = aCmd.HasOption ("pos", 6) ? gp_Dir (aCmd.ArgVec ("pos", 3)) : aManipulator->Position().Direction();
12481     gp_Dir aXDir     = aCmd.HasOption ("pos", 9) ? gp_Dir (aCmd.ArgVec ("pos", 6)) : aManipulator->Position().XDirection();
12482
12483     aManipulator->SetPosition (gp_Ax2 (aLocation, aVDir, aXDir));
12484   }
12485   if (aCmd.HasOption ("size", 1, Standard_True))
12486   {
12487     aManipulator->SetSize (aCmd.ArgFloat ("size"));
12488   }
12489   if (aCmd.HasOption ("zoomable", 1, Standard_True))
12490   {
12491     aManipulator->SetZoomPersistence (!aCmd.ArgBool ("zoomable"));
12492
12493     if (ViewerTest::GetAISContext()->IsDisplayed (aManipulator))
12494     {
12495       ViewerTest::GetAISContext()->Remove  (aManipulator, Standard_False);
12496       ViewerTest::GetAISContext()->Display (aManipulator, Standard_False);
12497     }
12498   }
12499
12500   // ---------------------------------------------------
12501   // attach, detach or access manipulator from an object
12502   // ---------------------------------------------------
12503
12504   if (aCmd.HasOption ("attach"))
12505   {
12506     // Find an object and attach manipulator to it
12507     if (!aCmd.HasOption ("attach", 1, Standard_True))
12508     {
12509       return 1;
12510     }
12511
12512     TCollection_AsciiString anObjName (aCmd.Arg ("attach", 0).c_str());
12513     Handle(AIS_InteractiveObject) anObject;
12514     if (!aMapAIS.Find2 (anObjName, anObject))
12515     {
12516       std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" does not exist.\n";
12517       return 1;
12518     }
12519
12520     for (ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators()); anIt.More(); anIt.Next())
12521     {
12522       if (anIt.Value()->IsAttached()
12523        && anIt.Value()->Object() == anObject)
12524       {
12525         std::cerr << theArgVec[0] << " error: AIS object \"" << anObjName << "\" already has manipulator.\n";
12526         return 1;
12527       }
12528     }
12529
12530     AIS_Manipulator::OptionsForAttach anOptions;
12531     if (aCmd.HasOption ("adjustPosition", 1, Standard_True))
12532     {
12533       anOptions.SetAdjustPosition (aCmd.ArgBool ("adjustPosition"));
12534     }
12535     if (aCmd.HasOption ("adjustSize", 1, Standard_True))
12536     {
12537       anOptions.SetAdjustSize (aCmd.ArgBool ("adjustSize"));
12538     }
12539     if (aCmd.HasOption ("enableModes", 1, Standard_True))
12540     {
12541       anOptions.SetEnableModes (aCmd.ArgBool ("enableModes"));
12542     }
12543
12544     aManipulator->Attach (anObject, anOptions);
12545
12546     // Check view option
12547     if (aCmd.HasOption ("view"))
12548     {
12549       if (!aCmd.HasOption ("view", 1, Standard_True))
12550       {
12551         return 1;
12552       }
12553       TCollection_AsciiString aViewString (aCmd.Arg ("view", 0).c_str());
12554       Handle(V3d_View) aView;
12555       if (aViewString.IsEqual ("active"))
12556       {
12557         aView = ViewerTest::CurrentView();
12558       }
12559       else // Check view name
12560       {
12561         ViewerTest_Names aViewNames (aViewString);
12562         if (!ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
12563         {
12564           std::cerr << theArgVec[0] << " error: wrong view name '" << aViewString << "'\n";
12565           return 1;
12566         }
12567         aView = ViewerTest_myViews.Find1 (aViewNames.GetViewName());
12568         if (aView.IsNull())
12569         {
12570           std::cerr << theArgVec[0] << " error: cannot find view with name '" << aViewString << "'\n";
12571           return 1;
12572         }
12573       }
12574       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
12575         anIter (ViewerTest_myViews); anIter.More(); anIter.Next())
12576       {
12577         ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, anIter.Value(), Standard_False);
12578       }
12579       ViewerTest::GetAISContext()->SetViewAffinity (aManipulator, aView, Standard_True);
12580     }
12581   }
12582
12583   // --------------------------------------
12584   // apply transformation using manipulator
12585   // --------------------------------------
12586
12587   if (aCmd.HasOption ("startTransform", 2, Standard_True))
12588   {
12589     aManipulator->StartTransform (aCmd.ArgInt ("startTransform", 0), aCmd.ArgInt ("startTransform", 1), ViewerTest::CurrentView());
12590   }
12591   if (aCmd.HasOption ("transform", 2, Standard_True))
12592   {
12593     aManipulator->Transform (aCmd.ArgInt ("transform", 0), aCmd.ArgInt ("transform", 1), ViewerTest::CurrentView());
12594   }
12595   if (aCmd.HasOption ("stopTransform"))
12596   {
12597     Standard_Boolean toApply = !aCmd.HasOption ("stopTransform", 1) || (aCmd.Arg ("stopTransform", 0) != "abort");
12598
12599     aManipulator->StopTransform (toApply);
12600   }
12601
12602   gp_Trsf aT;
12603   if (aCmd.HasOption ("move", 3, Standard_True))
12604   {
12605     aT.SetTranslationPart (aCmd.ArgVec ("move"));
12606   }
12607   if (aCmd.HasOption ("rotate", 7, Standard_True))
12608   {
12609     aT.SetRotation (gp_Ax1 (aCmd.ArgPnt ("rotate", 0), aCmd.ArgVec ("rotate", 3)), aCmd.ArgDouble ("rotate", 6));
12610   }
12611   if (aCmd.HasOption ("scale", 1))
12612   {
12613     aT.SetScale (gp_Pnt(), aCmd.ArgDouble("scale"));
12614   }
12615
12616   if (aT.Form() != gp_Identity)
12617   {
12618     aManipulator->Transform (aT);
12619   }
12620
12621   ViewerTest::GetAISContext()->Redisplay (aManipulator, Standard_True);
12622
12623   return 0;
12624 }
12625
12626 //===============================================================================================
12627 //function : VSelectionProperties
12628 //purpose  :
12629 //===============================================================================================
12630 static int VSelectionProperties (Draw_Interpretor& theDi,
12631                                  Standard_Integer  theArgsNb,
12632                                  const char**      theArgVec)
12633 {
12634   const Handle(AIS_InteractiveContext)& aCtx = ViewerTest::GetAISContext();
12635   if (aCtx.IsNull())
12636   {
12637     std::cerr << "No active viewer!\n";
12638     return 1;
12639   }
12640
12641   if (TCollection_AsciiString (theArgVec[0]) == "vhighlightselected")
12642   {
12643     // handle obsolete alias
12644     bool toEnable = true;
12645     if (theArgsNb < 2)
12646     {
12647       theDi << (aCtx->ToHilightSelected() ? "on" : "off");
12648       return 0;
12649     }
12650     else if (theArgsNb != 2
12651          || !ViewerTest::ParseOnOff (theArgVec[1], toEnable))
12652     {
12653       std::cout << "Syntax error: wrong number of parameters.";
12654       return 1;
12655     }
12656     if (toEnable != aCtx->ToHilightSelected())
12657     {
12658       aCtx->ClearDetected();
12659       aCtx->SetToHilightSelected (toEnable);
12660     }
12661     return 0;
12662   }
12663
12664   Standard_Boolean toPrint  = theArgsNb == 1;
12665   Standard_Boolean toRedraw = Standard_False;
12666   Standard_Integer anArgIter = 1;
12667   Prs3d_TypeOfHighlight aType = Prs3d_TypeOfHighlight_None;
12668   if (anArgIter < theArgsNb)
12669   {
12670     TCollection_AsciiString anArgFirst (theArgVec[anArgIter]);
12671     anArgFirst.LowerCase();
12672     ++anArgIter;
12673     if (anArgFirst == "dynhighlight"
12674      || anArgFirst == "dynhilight"
12675      || anArgFirst == "dynamichighlight"
12676      || anArgFirst == "dynamichilight")
12677     {
12678       aType = Prs3d_TypeOfHighlight_Dynamic;
12679     }
12680     else if (anArgFirst == "localdynhighlight"
12681           || anArgFirst == "localdynhilight"
12682           || anArgFirst == "localdynamichighlight"
12683           || anArgFirst == "localdynamichilight")
12684     {
12685       aType = Prs3d_TypeOfHighlight_LocalDynamic;
12686     }
12687     else if (anArgFirst == "selhighlight"
12688           || anArgFirst == "selhilight"
12689           || anArgFirst == "selectedhighlight"
12690           || anArgFirst == "selectedhilight")
12691     {
12692       aType = Prs3d_TypeOfHighlight_Selected;
12693     }
12694     else if (anArgFirst == "localselhighlight"
12695           || anArgFirst == "localselhilight"
12696           || anArgFirst == "localselectedhighlight"
12697           || anArgFirst == "localselectedhilight")
12698     {
12699       aType = Prs3d_TypeOfHighlight_LocalSelected;
12700     }
12701     else
12702     {
12703       --anArgIter;
12704     }
12705   }
12706   for (; anArgIter < theArgsNb; ++anArgIter)
12707   {
12708     TCollection_AsciiString anArg (theArgVec[anArgIter]);
12709     anArg.LowerCase();
12710     if (anArg == "-help")
12711     {
12712       theDi.PrintHelp (theArgVec[0]);
12713       return 0;
12714     }
12715     else if (anArg == "-print")
12716     {
12717       toPrint = Standard_True;
12718     }
12719     else if (anArg == "-autoactivate")
12720     {
12721       Standard_Boolean toEnable = Standard_True;
12722       if (anArgIter + 1 < theArgsNb
12723        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12724       {
12725         ++anArgIter;
12726       }
12727       aCtx->SetAutoActivateSelection (toEnable);
12728     }
12729     else if (anArg == "-automatichighlight"
12730           || anArg == "-automatichilight"
12731           || anArg == "-autohighlight"
12732           || anArg == "-autohilight")
12733     {
12734       Standard_Boolean toEnable = Standard_True;
12735       if (anArgIter + 1 < theArgsNb
12736        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12737       {
12738         ++anArgIter;
12739       }
12740       aCtx->ClearSelected (false);
12741       aCtx->ClearDetected();
12742       aCtx->SetAutomaticHilight (toEnable);
12743       toRedraw = true;
12744     }
12745     else if (anArg == "-highlightselected"
12746           || anArg == "-hilightselected")
12747     {
12748       Standard_Boolean toEnable = Standard_True;
12749       if (anArgIter + 1 < theArgsNb
12750        && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], toEnable))
12751       {
12752         ++anArgIter;
12753       }
12754       aCtx->ClearDetected();
12755       aCtx->SetToHilightSelected (toEnable);
12756       toRedraw = true;
12757     }
12758     else if (anArg == "-pickstrategy"
12759           || anArg == "-pickingstrategy")
12760     {
12761       if (++anArgIter >= theArgsNb)
12762       {
12763         std::cout << "Syntax error: type of highlighting is undefined\n";
12764         return 1;
12765       }
12766
12767       SelectMgr_PickingStrategy aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12768       TCollection_AsciiString aVal (theArgVec[anArgIter]);
12769       aVal.LowerCase();
12770       if (aVal == "first"
12771        || aVal == "firstaccepted"
12772        || aVal == "firstacceptable")
12773       {
12774         aStrategy = SelectMgr_PickingStrategy_FirstAcceptable;
12775       }
12776       else if (aVal == "topmost"
12777             || aVal == "onlyTopmost")
12778       {
12779         aStrategy = SelectMgr_PickingStrategy_OnlyTopmost;
12780       }
12781       else
12782       {
12783         std::cout << "Syntax error: unknwon picking strategy '" << aVal << "'\n";
12784         return 1;
12785       }
12786
12787       aCtx->SetPickingStrategy (aStrategy);
12788     }
12789     else if (anArg == "-pixtol"
12790           && anArgIter + 1 < theArgsNb)
12791     {
12792       aCtx->SetPixelTolerance (Draw::Atoi (theArgVec[++anArgIter]));
12793     }
12794     else if ((anArg == "-mode"
12795            || anArg == "-dispmode")
12796           && anArgIter + 1 < theArgsNb)
12797     {
12798       if (aType == Prs3d_TypeOfHighlight_None)
12799       {
12800         std::cout << "Syntax error: type of highlighting is undefined\n";
12801         return 1;
12802       }
12803
12804       const Standard_Integer aDispMode = Draw::Atoi (theArgVec[++anArgIter]);
12805       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12806       aStyle->SetDisplayMode (aDispMode);
12807       toRedraw = Standard_True;
12808     }
12809     else if (anArg == "-layer"
12810           && anArgIter + 1 < theArgsNb)
12811     {
12812       if (aType == Prs3d_TypeOfHighlight_None)
12813       {
12814         std::cout << "Syntax error: type of highlighting is undefined\n";
12815         return 1;
12816       }
12817
12818       ++anArgIter;
12819       Graphic3d_ZLayerId aNewLayer = Graphic3d_ZLayerId_UNKNOWN;
12820       if (!ViewerTest::ParseZLayer (theArgVec[anArgIter], aNewLayer))
12821       {
12822         std::cerr << "Error: wrong syntax at " << theArgVec[anArgIter] << ".\n";
12823         return 1;
12824       }
12825
12826       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12827       aStyle->SetZLayer (aNewLayer);
12828       toRedraw = Standard_True;
12829     }
12830     else if (anArg == "-hicolor"
12831           || anArg == "-selcolor"
12832           || anArg == "-color")
12833     {
12834       if (anArg.StartsWith ("-hi"))
12835       {
12836         aType = Prs3d_TypeOfHighlight_Dynamic;
12837       }
12838       else if (anArg.StartsWith ("-sel"))
12839       {
12840         aType = Prs3d_TypeOfHighlight_Selected;
12841       }
12842       else if (aType == Prs3d_TypeOfHighlight_None)
12843       {
12844         std::cout << "Syntax error: type of highlighting is undefined\n";
12845         return 1;
12846       }
12847
12848       Quantity_Color aColor;
12849       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgsNb - anArgIter - 1,
12850                                                            theArgVec + anArgIter + 1,
12851                                                            aColor);
12852       if (aNbParsed == 0)
12853       {
12854         std::cout << "Syntax error: need more arguments.\n";
12855         return 1;
12856       }
12857       anArgIter += aNbParsed;
12858
12859       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12860       aStyle->SetColor (aColor);
12861       toRedraw = Standard_True;
12862     }
12863     else if ((anArg == "-transp"
12864            || anArg == "-transparency"
12865            || anArg == "-hitransp"
12866            || anArg == "-seltransp"
12867            || anArg == "-hitransplocal"
12868            || anArg == "-seltransplocal")
12869           && anArgIter + 1 < theArgsNb)
12870     {
12871       if (anArg.StartsWith ("-hi"))
12872       {
12873         aType = Prs3d_TypeOfHighlight_Dynamic;
12874       }
12875       else if (anArg.StartsWith ("-sel"))
12876       {
12877         aType = Prs3d_TypeOfHighlight_Selected;
12878       }
12879       else if (aType == Prs3d_TypeOfHighlight_None)
12880       {
12881         std::cout << "Syntax error: type of highlighting is undefined\n";
12882         return 1;
12883       }
12884
12885       const Standard_Real aTransp = Draw::Atof (theArgVec[++anArgIter]);
12886       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12887       aStyle->SetTransparency ((Standard_ShortReal )aTransp);
12888       toRedraw = Standard_True;
12889     }
12890     else if ((anArg == "-mat"
12891            || anArg == "-material")
12892           && anArgIter + 1 < theArgsNb)
12893     {
12894       if (aType == Prs3d_TypeOfHighlight_None)
12895       {
12896         std::cout << "Syntax error: type of highlighting is undefined\n";
12897         return 1;
12898       }
12899
12900       const Handle(Prs3d_Drawer)& aStyle = aCtx->HighlightStyle (aType);
12901       Graphic3d_NameOfMaterial aMatName = Graphic3d_MaterialAspect::MaterialFromName (theArgVec[anArgIter + 1]);
12902       if (aMatName != Graphic3d_NOM_DEFAULT)
12903       {
12904         ++anArgIter;
12905         Handle(Graphic3d_AspectFillArea3d) anAspect = new Graphic3d_AspectFillArea3d();
12906         *anAspect = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect();
12907         Graphic3d_MaterialAspect aMat (aMatName);
12908         aMat.SetColor (aStyle->Color());
12909         aMat.SetTransparency (aStyle->Transparency());
12910         anAspect->SetFrontMaterial (aMat);
12911         anAspect->SetInteriorColor (aStyle->Color());
12912         aStyle->SetBasicFillAreaAspect (anAspect);
12913       }
12914       else
12915       {
12916         aStyle->SetBasicFillAreaAspect (Handle(Graphic3d_AspectFillArea3d)());
12917       }
12918       toRedraw = Standard_True;
12919     }
12920     else
12921     {
12922       std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
12923     }
12924   }
12925
12926   if (toPrint)
12927   {
12928     const Handle(Prs3d_Drawer)& aHiStyle  = aCtx->HighlightStyle();
12929     const Handle(Prs3d_Drawer)& aSelStyle = aCtx->SelectionStyle();
12930     theDi << "Auto-activation                : " << (aCtx->GetAutoActivateSelection() ? "On" : "Off") << "\n";
12931     theDi << "Auto-highlight                 : " << (aCtx->AutomaticHilight() ? "On" : "Off") << "\n";
12932     theDi << "Highlight selected             : " << (aCtx->ToHilightSelected() ? "On" : "Off") << "\n";
12933     theDi << "Selection pixel tolerance      : " << aCtx->MainSelector()->PixelTolerance() << "\n";
12934     theDi << "Selection color                : " << Quantity_Color::StringName (aSelStyle->Color().Name()) << "\n";
12935     theDi << "Dynamic highlight color        : " << Quantity_Color::StringName (aHiStyle->Color().Name()) << "\n";
12936     theDi << "Selection transparency         : " << aSelStyle->Transparency() << "\n";
12937     theDi << "Dynamic highlight transparency : " << aHiStyle->Transparency() << "\n";
12938     theDi << "Selection mode                 : " << aSelStyle->DisplayMode() << "\n";
12939     theDi << "Dynamic highlight mode         : " << aHiStyle->DisplayMode() << "\n";
12940     theDi << "Selection layer                : " << aSelStyle->ZLayer() << "\n";
12941     theDi << "Dynamic layer                  : " << aHiStyle->ZLayer() << "\n";
12942   }
12943
12944   if (aCtx->NbSelected() != 0 && toRedraw)
12945   {
12946     aCtx->HilightSelected (Standard_True);
12947   }
12948
12949   return 0;
12950 }
12951
12952 //===============================================================================================
12953 //function : VDumpSelectionImage
12954 //purpose  :
12955 //===============================================================================================
12956 static int VDumpSelectionImage (Draw_Interpretor& /*theDi*/,
12957                                 Standard_Integer  theArgsNb,
12958                                 const char**      theArgVec)
12959 {
12960   if (theArgsNb < 2)
12961   {
12962     std::cout << "Syntax error: wrong number arguments for '" << theArgVec[0] << "'\n";
12963     return 1;
12964   }
12965
12966   const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
12967   if (aContext.IsNull())
12968   {
12969     std::cout << "Error: no active view.\n";
12970     return 1;
12971   }
12972
12973   TCollection_AsciiString aFile;
12974   StdSelect_TypeOfSelectionImage aType = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12975   Image_Format anImgFormat = Image_Format_BGR;
12976   Standard_Integer aPickedIndex = 1;
12977   for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
12978   {
12979     TCollection_AsciiString aParam (theArgVec[anArgIter]);
12980     aParam.LowerCase();
12981     if (aParam == "-type")
12982     {
12983       if (++anArgIter >= theArgsNb)
12984       {
12985         std::cout << "Syntax error: wrong number parameters of flag '-depth'.\n";
12986         return 1;
12987       }
12988
12989       TCollection_AsciiString aValue (theArgVec[anArgIter]);
12990       aValue.LowerCase();
12991       if (aValue == "depth"
12992        || aValue == "normdepth"
12993        || aValue == "normalizeddepth")
12994       {
12995         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepth;
12996         anImgFormat = Image_Format_GrayF;
12997       }
12998       if (aValue == "depthinverted"
12999        || aValue == "normdepthinverted"
13000        || aValue == "normalizeddepthinverted"
13001        || aValue == "inverted")
13002       {
13003         aType       = StdSelect_TypeOfSelectionImage_NormalizedDepthInverted;
13004         anImgFormat = Image_Format_GrayF;
13005       }
13006       else if (aValue == "unnormdepth"
13007             || aValue == "unnormalizeddepth")
13008       {
13009         aType       = StdSelect_TypeOfSelectionImage_UnnormalizedDepth;
13010         anImgFormat = Image_Format_GrayF;
13011       }
13012       else if (aValue == "objectcolor"
13013             || aValue == "object"
13014             || aValue == "color")
13015       {
13016         aType = StdSelect_TypeOfSelectionImage_ColoredDetectedObject;
13017       }
13018       else if (aValue == "entitycolor"
13019             || aValue == "entity")
13020       {
13021         aType = StdSelect_TypeOfSelectionImage_ColoredEntity;
13022       }
13023       else if (aValue == "ownercolor"
13024             || aValue == "owner")
13025       {
13026         aType = StdSelect_TypeOfSelectionImage_ColoredOwner;
13027       }
13028       else if (aValue == "selectionmodecolor"
13029             || aValue == "selectionmode"
13030             || aValue == "selmodecolor"
13031             || aValue == "selmode")
13032       {
13033         aType = StdSelect_TypeOfSelectionImage_ColoredSelectionMode;
13034       }
13035     }
13036     else if (aParam == "-picked"
13037           || aParam == "-pickeddepth"
13038           || aParam == "-pickedindex")
13039     {
13040       if (++anArgIter >= theArgsNb)
13041       {
13042         std::cout << "Syntax error: wrong number parameters at '" << aParam << "'.\n";
13043         return 1;
13044       }
13045
13046       aPickedIndex = Draw::Atoi (theArgVec[anArgIter]);
13047     }
13048     else if (aFile.IsEmpty())
13049     {
13050       aFile = theArgVec[anArgIter];
13051     }
13052     else
13053     {
13054       std::cout << "Syntax error: unknown argument '" << theArgVec[anArgIter] << "'.\n";
13055       return 1;
13056     }
13057   }
13058   if (aFile.IsEmpty())
13059   {
13060     std::cout << "Syntax error: image file name is missing.\n";
13061     return 1;
13062   }
13063
13064   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
13065   Standard_Integer aWidth = 0, aHeight = 0;
13066   aView->Window()->Size (aWidth, aHeight);
13067
13068   Image_AlienPixMap aPixMap;
13069   if (!aPixMap.InitZero (anImgFormat, aWidth, aHeight))
13070   {
13071     std::cout << "Error: can't allocate image.\n";
13072     return 1;
13073   }
13074   if (!aContext->MainSelector()->ToPixMap (aPixMap, aView, aType, aPickedIndex))
13075   {
13076     std::cout << "Error: can't generate selection image.\n";
13077     return 1;
13078   }
13079   if (!aPixMap.Save (aFile))
13080   {
13081     std::cout << "Error: can't save selection image.\n";
13082     return 0;
13083   }
13084   return 0;
13085 }
13086
13087 //=======================================================================
13088 //function : ViewerCommands
13089 //purpose  :
13090 //=======================================================================
13091
13092 void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
13093 {
13094
13095   const char *group = "ZeViewer";
13096   theCommands.Add("vinit",
13097           "vinit [-name viewName] [-left leftPx] [-top topPx] [-width widthPx] [-height heightPx]"
13098     "\n\t\t:     [-exitOnClose] [-closeOnEscape] [-cloneActive] [-2d_mode {on|off}=off]"
13099   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13100     "\n\t\t:     [-display displayName]"
13101   #endif
13102     "\n\t\t: Creates new View window with specified name viewName."
13103     "\n\t\t: By default the new view is created in the viewer and in"
13104     "\n\t\t: graphic driver shared with active view."
13105     "\n\t\t:  -name {driverName/viewerName/viewName | viewerName/viewName | viewName}"
13106     "\n\t\t: If driverName isn't specified the driver will be shared with active view."
13107     "\n\t\t: If viewerName isn't specified the viewer will be shared with active view."
13108 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
13109     "\n\t\t:  -display HostName.DisplayNumber[:ScreenNumber]"
13110     "\n\t\t: Display name will be used within creation of graphic driver, when specified."
13111 #endif
13112     "\n\t\t:  -left,  -top    pixel position of left top corner of the window."
13113     "\n\t\t:  -width, -height width and heigth of window respectively."
13114     "\n\t\t:  -cloneActive floag to copy camera and dimensions of active view."
13115     "\n\t\t:  -exitOnClose when specified, closing the view will exit application."
13116     "\n\t\t:  -closeOnEscape when specified, view will be closed on pressing Escape."
13117     "\n\t\t:  -2d_mode when on, view will not react on rotate scene events"
13118     "\n\t\t: Additional commands for operations with views: vclose, vactivate, vviewlist.",
13119     __FILE__,VInit,group);
13120   theCommands.Add("vclose" ,
13121     "[view_id [keep_context=0|1]]\n"
13122     "or vclose ALL - to remove all created views\n"
13123     " - removes view(viewer window) defined by its view_id.\n"
13124     " - keep_context: by default 0; if 1 and the last view is deleted"
13125     " the current context is not removed.",
13126     __FILE__,VClose,group);
13127   theCommands.Add("vactivate" ,
13128     "vactivate view_id [-noUpdate]"
13129     " - activates view(viewer window) defined by its view_id",
13130     __FILE__,VActivate,group);
13131   theCommands.Add("vviewlist",
13132     "vviewlist [format={tree, long}]"
13133     " - prints current list of views per viewer and graphic_driver ID shared between viewers"
13134     " - format: format of result output, if tree the output is a tree view;"
13135     "otherwise it's a list of full view names. By default format = tree",
13136     __FILE__,VViewList,group);
13137   theCommands.Add("vhelp" ,
13138     "vhelp            : display help on the viewer commands",
13139     __FILE__,VHelp,group);
13140   theCommands.Add("vviewproj",
13141           "vviewproj [top|bottom|left|right|front|back|axoLeft|axoRight]"
13142     "\n\t\t:         [+-X+-Y+-Z] [-Zup|-Yup] [-frame +-X+-Y]"
13143     "\n\t\t: Setup view direction"
13144     "\n\t\t:   -Yup      use Y-up convention instead of Zup (which is default)."
13145     "\n\t\t:   +-X+-Y+-Z define direction as combination of DX, DY and DZ;"
13146     "\n\t\t:             for example '+Z' will show front of the model,"
13147     "\n\t\t:             '-X-Y+Z' will define left axonometrical view."
13148     "\n\t\t:   -frame    define camera Up and Right directions (regardless Up convention);"
13149     "\n\t\t:             for example '+X+Z' will show front of the model with Z-up."
13150     __FILE__,VViewProj,group);
13151   theCommands.Add("vtop" ,
13152     "vtop or <T>      : Top view. Orientation +X+Y" ,
13153     __FILE__,VViewProj,group);
13154   theCommands.Add("vbottom" ,
13155     "vbottom          : Bottom view. Orientation +X-Y" ,
13156     __FILE__,VViewProj,group);
13157   theCommands.Add("vleft" ,
13158     "vleft            : Left view. Orientation -Y+Z" ,
13159     __FILE__,VViewProj,group);
13160   theCommands.Add("vright" ,
13161     "vright           : Right view. Orientation +Y+Z" ,
13162     __FILE__,VViewProj,group);
13163   theCommands.Add("vaxo" ,
13164     " vaxo or <A>     : Axonometric view. Orientation +X-Y+Z",
13165     __FILE__,VViewProj,group);
13166   theCommands.Add("vfront" ,
13167     "vfront           : Front view. Orientation +X+Z" ,
13168     __FILE__,VViewProj,group);
13169   theCommands.Add("vback" ,
13170     "vback            : Back view. Orientation -X+Z" ,
13171     __FILE__,VViewProj,group);
13172   theCommands.Add("vpick" ,
13173     "vpick           : vpick X Y Z [shape subshape] ( all variables as string )",
13174     VPick,group);
13175   theCommands.Add("vfit",
13176     "vfit or <F> [-selected] [-noupdate]"
13177     "\n\t\t: [-selected] fits the scene according to bounding box of currently selected objects",
13178     __FILE__,VFit,group);
13179   theCommands.Add ("vfitarea",
13180     "vfitarea x1 y1 x2 y2"
13181     "\n\t\t: vfitarea x1 y1 z1 x2 y2 z2"
13182     "\n\t\t: Fit view to show area located between two points"
13183     "\n\t\t: given in world 2D or 3D corrdinates.",
13184     __FILE__, VFitArea, group);
13185   theCommands.Add ("vzfit", "vzfit [scale]\n"
13186     "   Matches Z near, Z far view volume planes to the displayed objects.\n"
13187     "   \"scale\" - specifies factor to scale computed z range.\n",
13188     __FILE__, VZFit, group);
13189   theCommands.Add("vrepaint",
13190             "vrepaint [-immediate] [-continuous FPS]"
13191     "\n\t\t: force redraw of active View"
13192     "\n\t\t:   -immediate  flag performs redraw of immediate layers only;"
13193     "\n\t\t:   -continuous activates/deactivates continuous redraw of active View,"
13194     "\n\t\t:                0 means no continuous rendering,"
13195     "\n\t\t:               -1 means non-stop redraws,"
13196     "\n\t\t:               >0 specifies target framerate,",
13197     __FILE__,VRepaint,group);
13198   theCommands.Add("vclear",
13199     "vclear          : vclear"
13200     "\n\t\t: remove all the object from the viewer",
13201     __FILE__,VClear,group);
13202   theCommands.Add (
13203     "vbackground",
13204     "Changes background or some background settings.\n"
13205     "\n"
13206     "Usage:\n"
13207     "  vbackground -imageFile ImageFile [-imageMode FillType]\n"
13208     "  vbackground -imageMode FillType\n"
13209     "  vbackground -gradient Color1 Color2 [-gradientMode FillMethod]\n"
13210     "  vbackground -gradientMode FillMethod\n"
13211     "  vbackground -color Color\n"
13212     "  vbackground -default -gradient Color1 Color2 [-gradientMode FillType]\n"
13213     "  vbackground -default -color Color\n"
13214     "  vbackground -help\n"
13215     "\n"
13216     "Options:\n"
13217     "  -imageFile    (-imgFile, -image, -img):             sets filename of image used as background\n"
13218     "  -imageMode    (-imgMode, -imageMd, -imgMd):         sets image fill type\n"
13219     "  -gradient     (-grad, -gr):                         sets background gradient starting and ending colors\n"
13220     "  -gradientMode (-gradMode, -gradMd, -grMode, -grMd): sets gradient fill method\n"
13221     "  -color        (-col):                               sets background color\n"
13222     "  -default      (-def):                               sets background default gradient or color\n"
13223     "  -help         (-h):                                 outputs short help message\n"
13224     "\n"
13225     "Arguments:\n"
13226     "  Color:      Red Green Blue  - where Red, Green, Blue must be integers within the range [0, 255]\n"
13227     "                                  or reals within the range [0.0, 1.0]\n"
13228     "              ColorName       - one of WHITE, BLACK, RED, GREEN, BLUE, etc.\n"
13229     "              #HHH, [#]HHHHHH - where H is a hexadecimal digit (0 .. 9, a .. f, or A .. F)\n"
13230     "  FillMethod: one of NONE, HOR[IZONTAL], VER[TICAL], DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, "
13231     "CORNER4\n"
13232     "  FillType:   one of CENTERED, TILED, STRETCH, NONE\n"
13233     "  ImageFile:  a name of the file with the image used as a background\n",
13234     __FILE__,
13235     vbackground,
13236     group);
13237   theCommands.Add ("vsetbg",
13238                    "Loads image as background."
13239                    "\n\t\t: vsetbg ImageFile [FillType]"
13240                    "\n\t\t: vsetbg -imageFile ImageFile [-imageMode FillType]"
13241                    "\n\t\t: Alias for 'vbackground -imageFile ImageFile [-imageMode FillType]'.",
13242                    __FILE__,
13243                    vbackground,
13244                    group);
13245   theCommands.Add ("vsetbgmode",
13246                    "Changes background image fill type."
13247                    "\n\t\t: vsetbgmode [-imageMode] FillType"
13248                    "\n\t\t: Alias for 'vbackground -imageMode FillType'.",
13249                    __FILE__,
13250                    vbackground,
13251                    group);
13252   theCommands.Add ("vsetgradientbg",
13253                    "Mounts gradient background."
13254                    "\n\t\t: vsetgradientbg Color1 Color2 [FillMethod]"
13255                    "\n\t\t: vsetgradientbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13256                    "\n\t\t: Alias for 'vbackground -gradient Color1 Color2 -gradientMode FillMethod'.",
13257                    __FILE__,
13258                    vbackground,
13259                    group);
13260   theCommands.Add ("vsetgrbgmode",
13261                    "Changes gradient background fill method."
13262                    "\n\t\t: vsetgrbgmode [-gradientMode] FillMethod"
13263                    "\n\t\t: Alias for 'vbackground -gradientMode FillMethod'.",
13264                    __FILE__,
13265                    vbackground,
13266                    group);
13267   theCommands.Add ("vsetcolorbg",
13268                    "Sets background color."
13269                    "\n\t\t: vsetcolorbg [-color] Color."
13270                    "\n\t\t: Alias for 'vbackground -color Color'.",
13271                    __FILE__,
13272                    vbackground,
13273                    group);
13274   theCommands.Add ("vsetdefaultbg",
13275                    "Sets default viewer background fill color (flat/gradient)."
13276                    "\n\t\t: vsetdefaultbg Color1 Color2 [FillMethod]"
13277                    "\n\t\t: vsetdefaultbg -gradient Color1 Color2 [-gradientMode FillMethod]"
13278                    "\n\t\t: Alias for 'vbackground -default -gradient Color1 Color2 [-gradientMode FillMethod]'."
13279                    "\n\t\t: vsetdefaultbg [-color] Color"
13280                    "\n\t\t: Alias for 'vbackground -default -color Color'.",
13281                    __FILE__,
13282                    vbackground,
13283                    group);
13284   theCommands.Add("vscale",
13285     "vscale          : vscale X Y Z",
13286     __FILE__,VScale,group);
13287   theCommands.Add("vzbufftrihedron",
13288             "vzbufftrihedron [{-on|-off}=-on] [-type {wireframe|zbuffer}=zbuffer]"
13289     "\n\t\t:       [-position center|left_lower|left_upper|right_lower|right_upper]"
13290     "\n\t\t:       [-scale value=0.1] [-size value=0.8] [-arrowDiam value=0.05]"
13291     "\n\t\t:       [-colorArrowX color=RED] [-colorArrowY color=GREEN] [-colorArrowZ color=BLUE]"
13292     "\n\t\t:       [-nbfacets value=12] [-colorLabels color=WHITE]"
13293     "\n\t\t: Displays a trihedron",
13294     __FILE__,VZBuffTrihedron,group);
13295   theCommands.Add("vrotate",
13296     "vrotate [[-mouseStart X Y] [-mouseMove X Y]]|[AX AY AZ [X Y Z]]"
13297     "\n                : Option -mouseStart starts rotation according to the mouse position"
13298     "\n                : Option -mouseMove continues rotation with angle computed"
13299     "\n                : from last and new mouse position."
13300     "\n                : vrotate AX AY AZ [X Y Z]",
13301     __FILE__,VRotate,group);
13302   theCommands.Add("vzoom",
13303     "vzoom           : vzoom coef",
13304     __FILE__,VZoom,group);
13305   theCommands.Add("vpan",
13306     "vpan            : vpan dx dy",
13307     __FILE__,VPan,group);
13308   theCommands.Add("vcolorscale",
13309     "vcolorscale name [-noupdate|-update] [-demo]"
13310     "\n\t\t:       [-range RangeMin=0 RangeMax=1 NbIntervals=10]"
13311     "\n\t\t:       [-font HeightFont=20]"
13312     "\n\t\t:       [-logarithmic {on|off}=off] [-reversed {on|off}=off]"
13313     "\n\t\t:       [-smoothTransition {on|off}=off]"
13314     "\n\t\t:       [-hueRange MinAngle=230 MaxAngle=0]"
13315     "\n\t\t:       [-colorRange MinColor=BLUE1 MaxColor=RED]"
13316     "\n\t\t:       [-textpos {left|right|center|none}=right]"
13317     "\n\t\t:       [-labelAtBorder {on|off}=on]"
13318     "\n\t\t:       [-colors Color1 Color2 ...] [-color Index Color]"
13319     "\n\t\t:       [-labels Label1 Label2 ...] [-label Index Label]"
13320     "\n\t\t:       [-freeLabels NbOfLabels Label1 Label2 ...]"
13321     "\n\t\t:       [-xy Left=0 Bottom=0]"
13322     "\n\t\t:  -demo     - displays a color scale with demonstratio values"
13323     "\n\t\t:  -colors   - set colors for all intervals"
13324     "\n\t\t:  -color    - set color for specific interval"
13325     "\n\t\t:  -textpos  - horizontal label position relative to color scale bar"
13326     "\n\t\t:  -labelAtBorder - vertical label position relative to color interval;"
13327     "\n\t\t:              at border means the value inbetween neighbor intervals,"
13328     "\n\t\t:              at center means the center value within current interval"
13329     "\n\t\t:  -labels   - set labels for all intervals"
13330     "\n\t\t:  -freeLabels - same as -labels but does not require"
13331     "\n\t\t:              matching the number of intervals"
13332     "\n\t\t:  -label    - set label for specific interval"
13333     "\n\t\t:  -title    - set title"
13334     "\n\t\t:  -reversed - setup smooth color transition between intervals"
13335     "\n\t\t:  -smoothTransition - swap colorscale direction"
13336     "\n\t\t:  -hueRange - set hue angles corresponding to minimum and maximum values"
13337     __FILE__, VColorScale, group);
13338   theCommands.Add("vgraduatedtrihedron",
13339     "vgraduatedtrihedron : -on/-off [-xname Name] [-yname Name] [-zname Name] [-arrowlength Value]\n"
13340     "\t[-namefont Name] [-valuesfont Name]\n"
13341     "\t[-xdrawname on/off] [-ydrawname on/off] [-zdrawname on/off]\n"
13342     "\t[-xnameoffset IntVal] [-ynameoffset IntVal] [-znameoffset IntVal]"
13343     "\t[-xnamecolor Color] [-ynamecolor Color] [-znamecolor Color]\n"
13344     "\t[-xdrawvalues on/off] [-ydrawvalues on/off] [-zdrawvalues on/off]\n"
13345     "\t[-xvaluesoffset IntVal] [-yvaluesoffset IntVal] [-zvaluesoffset IntVal]"
13346     "\t[-xcolor Color] [-ycolor Color] [-zcolor Color]\n"
13347     "\t[-xdrawticks on/off] [-ydrawticks on/off] [-zdrawticks on/off]\n"
13348     "\t[-xticks Number] [-yticks Number] [-zticks Number]\n"
13349     "\t[-xticklength IntVal] [-yticklength IntVal] [-zticklength IntVal]\n"
13350     "\t[-drawgrid on/off] [-drawaxes on/off]\n"
13351     " - Displays or erases graduated trihedron"
13352     " - xname, yname, zname - names of axes, default: X, Y, Z\n"
13353     " - namefont - font of axes names. Default: Arial\n"
13354     " - xnameoffset, ynameoffset, znameoffset - offset of name from values or tickmarks or axis. Default: 30\n"
13355     " - xnamecolor, ynamecolor, znamecolor - colors of axes names\n"
13356     " - xvaluesoffset, yvaluesoffset, zvaluesoffset - offset of values from tickmarks or axis. Default: 10\n"
13357     " - valuesfont - font of axes values. Default: Arial\n"
13358     " - xcolor, ycolor, zcolor - color of axis and values\n"
13359     " - xticks, yticks, xzicks - number of tickmark on axes. Default: 5\n"
13360     " - xticklength, yticklength, xzicklength - length of tickmark on axes. Default: 10\n",
13361     __FILE__,VGraduatedTrihedron,group);
13362   theCommands.Add("vtile" ,
13363             "vtile [-totalSize W H] [-lowerLeft X Y] [-upperLeft X Y] [-tileSize W H]"
13364     "\n\t\t: Setup view to draw a tile (a part of virtual bigger viewport)."
13365     "\n\t\t:  -totalSize the size of virtual bigger viewport"
13366     "\n\t\t:  -tileSize  tile size (the view size will be used if omitted)"
13367     "\n\t\t:  -lowerLeft tile offset as lower left corner"
13368     "\n\t\t:  -upperLeft tile offset as upper left corner",
13369     __FILE__, VTile, group);
13370   theCommands.Add("vzlayer",
13371               "vzlayer [layerId]"
13372       "\n\t\t:         [-add|-delete|-get|-settings] [-insertBefore AnotherLayer] [-insertAfter AnotherLayer]"
13373       "\n\t\t:         [-origin X Y Z] [-cullDist Distance] [-cullSize Size]"
13374       "\n\t\t:         [-enable|-disable {depthTest|depthWrite|depthClear|depthoffset}]"
13375       "\n\t\t:         [-enable|-disable {positiveOffset|negativeOffset|textureenv|rayTracing}]"
13376       "\n\t\t: ZLayer list management:"
13377       "\n\t\t:   -add      add new z layer to viewer and print its id"
13378       "\n\t\t:   -insertBefore add new z layer and insert it before existing one"
13379       "\n\t\t:   -insertAfter  add new z layer and insert it after  existing one"
13380       "\n\t\t:   -delete   delete z layer"
13381       "\n\t\t:   -get      print sequence of z layers"
13382       "\n\t\t:   -settings print status of z layer settings"
13383       "\n\t\t:   -disable  disables given setting"
13384       "\n\t\t:   -enable   enables  given setting",
13385     __FILE__,VZLayer,group);
13386   theCommands.Add("vlayerline",
13387     "vlayerline : vlayerline x1 y1 x2 y2 [linewidth=0.5] [linetype=0] [transparency=1.0]",
13388     __FILE__,VLayerLine,group);
13389   theCommands.Add("vgrid",
13390               "vgrid [off] [-type {rect|circ}] [-mode {line|point}] [-origin X Y] [-rotAngle Angle] [-zoffset DZ]"
13391       "\n\t\t:       [-step X Y] [-size DX DY]"
13392       "\n\t\t:       [-step StepRadius NbDivisions] [-radius Radius]",
13393     __FILE__, VGrid, group);
13394   theCommands.Add ("vpriviledgedplane",
13395     "vpriviledgedplane [Ox Oy Oz Nx Ny Nz [Xx Xy Xz]]"
13396     "\n\t\t:   Ox, Oy, Oz - plane origin"
13397     "\n\t\t:   Nx, Ny, Nz - plane normal direction"
13398     "\n\t\t:   Xx, Xy, Xz - plane x-reference axis direction"
13399     "\n\t\t: Sets or prints viewer's priviledged plane geometry.",
13400     __FILE__, VPriviledgedPlane, group);
13401   theCommands.Add ("vconvert",
13402     "vconvert v [Mode={window|view}]"
13403     "\n\t\t: vconvert x y [Mode={window|view|grid|ray}]"
13404     "\n\t\t: vconvert x y z [Mode={window|grid}]"
13405     "\n\t\t:   window - convert to window coordinates, pixels"
13406     "\n\t\t:   view   - convert to view projection plane"
13407     "\n\t\t:   grid   - convert to model coordinates, given on grid"
13408     "\n\t\t:   ray    - convert projection ray to model coordiantes"
13409     "\n\t\t: - vconvert v window : convert view to window;"
13410     "\n\t\t: - vconvert v view   : convert window to view;"
13411     "\n\t\t: - vconvert x y window : convert view to window;"
13412     "\n\t\t: - vconvert x y view : convert window to view;"
13413     "\n\t\t: - vconvert x y : convert window to model;"
13414     "\n\t\t: - vconvert x y grid : convert window to model using grid;"
13415     "\n\t\t: - vconvert x y ray : convert window projection line to model;"
13416     "\n\t\t: - vconvert x y z window : convert model to window;"
13417     "\n\t\t: - vconvert x y z grid : convert view to model using grid;"
13418     "\n\t\t: Converts the given coordinates to window/view/model space.",
13419     __FILE__, VConvert, group);
13420   theCommands.Add ("vfps",
13421     "vfps [framesNb=100] [-duration seconds] : estimate average frame rate for active view",
13422     __FILE__, VFps, group);
13423   theCommands.Add ("vgldebug",
13424             "vgldebug [-sync {0|1}] [-debug {0|1}] [-glslWarn {0|1}]"
13425     "\n\t\t:          [-glslCode {off|short|full}] [-extraMsg {0|1}] [{0|1}]"
13426     "\n\t\t: Request debug GL context. Should be called BEFORE vinit."
13427     "\n\t\t: Debug context can be requested only on Windows"
13428     "\n\t\t: with GL_ARB_debug_output extension implemented by GL driver!"
13429     "\n\t\t:  -sync     - request synchronized debug GL context"
13430     "\n\t\t:  -glslWarn - log GLSL compiler/linker warnings,"
13431     "\n\t\t:              which are suppressed by default,"
13432     "\n\t\t:  -glslCode - log GLSL program source code,"
13433     "\n\t\t:              which are suppressed by default,"
13434     "\n\t\t:  -extraMsg - log extra diagnostic messages from GL context,"
13435     "\n\t\t:              which are suppressed by default",
13436     __FILE__, VGlDebug, group);
13437   theCommands.Add ("vvbo",
13438     "vvbo [{0|1}] : turn VBO usage On/Off; affects only newly displayed objects",
13439     __FILE__, VVbo, group);
13440   theCommands.Add ("vstereo",
13441             "vstereo [0|1] [-mode Mode] [-reverse {0|1}]"
13442     "\n\t\t:         [-anaglyph Filter]"
13443     "\n\t\t: Control stereo output mode. Available modes for -mode:"
13444     "\n\t\t:  quadBuffer        - OpenGL QuadBuffer stereo,"
13445     "\n\t\t:                     requires driver support."
13446     "\n\t\t:                     Should be called BEFORE vinit!"
13447     "\n\t\t:  anaglyph         - Anaglyph glasses"
13448     "\n\t\t:  rowInterlaced    - row-interlaced display"
13449     "\n\t\t:  columnInterlaced - column-interlaced display"
13450     "\n\t\t:  chessBoard       - chess-board output"
13451     "\n\t\t:  sideBySide       - horizontal pair"
13452     "\n\t\t:  overUnder        - vertical   pair"
13453     "\n\t\t: Available Anaglyph filters for -anaglyph:"
13454     "\n\t\t:  redCyan, redCyanSimple, yellowBlue, yellowBlueSimple,"
13455     "\n\t\t:  greenMagentaSimple",
13456     __FILE__, VStereo, group);
13457   theCommands.Add ("vcaps",
13458             "vcaps [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]"
13459     "\n\t\t:       [-compatibleProfile {0|1}]"
13460     "\n\t\t:       [-vsync {0|1}] [-useWinBuffer {0|1}]"
13461     "\n\t\t:       [-quadBuffer {0|1}] [-stereo {0|1}]"
13462     "\n\t\t:       [-softMode {0|1}] [-noupdate|-update]"
13463     "\n\t\t: Modify particular graphic driver options:"
13464     "\n\t\t:  FFP      - use fixed-function pipeline instead of"
13465     "\n\t\t:             built-in GLSL programs"
13466     "\n\t\t:            (requires compatible profile)"
13467     "\n\t\t:  polygonMode - use Polygon Mode instead of built-in GLSL programs"
13468     "\n\t\t:  VBO      - use Vertex Buffer Object (copy vertex"
13469     "\n\t\t:             arrays to GPU memory)"
13470     "\n\t\t:  sprite   - use textured sprites instead of bitmaps"
13471     "\n\t\t:  vsync    - switch VSync on or off"
13472     "\n\t\t:  winBuffer - allow using window buffer for rendering"
13473     "\n\t\t: Context creation options:"
13474     "\n\t\t:  softMode          - software OpenGL implementation"
13475     "\n\t\t:  compatibleProfile - backward-compatible profile"
13476     "\n\t\t:  quadbuffer        - QuadBuffer"
13477     "\n\t\t: Unlike vrenderparams, these parameters control alternative"
13478     "\n\t\t: rendering paths producing the same visual result when"
13479     "\n\t\t: possible."
13480     "\n\t\t: Command is intended for testing old hardware compatibility.",
13481     __FILE__, VCaps, group);
13482   theCommands.Add ("vmemgpu",
13483     "vmemgpu [f]: print system-dependent GPU memory information if available;"
13484     " with f option returns free memory in bytes",
13485     __FILE__, VMemGpu, group);
13486   theCommands.Add ("vreadpixel",
13487     "vreadpixel xPixel yPixel [{rgb|rgba|depth|hls|rgbf|rgbaf}=rgba] [-name]"
13488     " : Read pixel value for active view",
13489     __FILE__, VReadPixel, group);
13490   theCommands.Add("diffimage",
13491             "diffimage imageFile1 imageFile2 [diffImageFile]"
13492     "\n\t\t:           [-toleranceOfColor {0..1}=0] [-blackWhite {on|off}=off] [-borderFilter {on|off}=off]"
13493     "\n\t\t:           [-display viewName prsName1 prsName2 prsNameDiff] [-exitOnClose] [-closeOnEscape]"
13494     "\n\t\t: Compare two images by content and generate difference image."
13495     "\n\t\t: When -exitOnClose is specified, closing the view will exit application."
13496     "\n\t\t: When -closeOnEscape is specified, view will be closed on pressing Escape.",
13497     __FILE__, VDiffImage, group);
13498   theCommands.Add ("vselect",
13499     "vselect x1 y1 [x2 y2 [x3 y3 ... xn yn]] [-allowoverlap 0|1] [shift_selection = 0|1]\n"
13500     "- emulates different types of selection:\n"
13501     "- 1) single click selection\n"
13502     "- 2) selection with rectangle having corners at pixel positions (x1,y1) and (x2,y2)\n"
13503     "- 3) selection with polygon having corners in pixel positions (x1,y1), (x2,y2),...,(xn,yn)\n"
13504     "- 4) -allowoverlap manages overlap and inclusion detection in rectangular selection.\n"
13505     "     If the flag is set to 1, both sensitives that were included completely and overlapped partially by defined rectangle will be detected,\n"
13506     "     otherwise algorithm will chose only fully included sensitives. Default behavior is to detect only full inclusion. "
13507     " (partial inclusion - overlap - is not allowed by default)\n"
13508     "- 5) any of these selections with shift button pressed",
13509     __FILE__, VSelect, group);
13510   theCommands.Add ("vmoveto",
13511     "vmoveto [x y] [-reset]"
13512     "\n\t\t: Emulates cursor movement to pixel position (x,y)."
13513     "\n\t\t:   -reset resets current highlighting",
13514     __FILE__, VMoveTo, group);
13515   theCommands.Add ("vviewparams",
13516               "vviewparams [-args] [-scale [s]]"
13517       "\n\t\t:             [-eye [x y z]] [-at [x y z]] [-up [x y z]]"
13518       "\n\t\t:             [-proj [x y z]] [-center x y] [-size sx]"
13519       "\n\t\t: Manage current view parameters or prints all"
13520       "\n\t\t: current values when called without argument."
13521       "\n\t\t:   -scale [s]    prints or sets viewport relative scale"
13522       "\n\t\t:   -eye  [x y z] prints or sets eye location"
13523       "\n\t\t:   -at   [x y z] prints or sets center of look"
13524       "\n\t\t:   -up   [x y z] prints or sets direction of up vector"
13525       "\n\t\t:   -proj [x y z] prints or sets direction of look"
13526       "\n\t\t:   -center x y   sets location of center of the screen in pixels"
13527       "\n\t\t:   -size [sx]    prints viewport projection width and height sizes"
13528       "\n\t\t:                 or changes the size of its maximum dimension"
13529       "\n\t\t:   -args         prints vviewparams arguments for restoring current view",
13530     __FILE__, VViewParams, group);
13531
13532   theCommands.Add("v2dmode",
13533     "v2dmode [-name viewName] [-mode {-on|-off}=-on]"
13534     "\n\t\t:   name   - name of existing view, if not defined, the active view is changed"
13535     "\n\t\t:   mode   - switches On/Off rotation mode"
13536     "\n\t\t: Set 2D mode of the active viewer manipulating. The following mouse and key actions are disabled:"
13537     "\n\t\t:   - rotation of the view by 3rd mouse button with Ctrl active"
13538     "\n\t\t:   - set view projection using key buttons: A/D/T/B/L/R for AXO, Reset, Top, Bottom, Left, Right"
13539     "\n\t\t: View camera position might be changed only by commands.",
13540     __FILE__, V2DMode, group);
13541
13542   theCommands.Add("vanimation", "Alias for vanim",
13543     __FILE__, VAnimation, group);
13544
13545   theCommands.Add("vanim",
13546             "List existing animations:"
13547     "\n\t\t:  vanim"
13548     "\n\t\t: Animation playback:"
13549     "\n\t\t:  vanim name -play|-resume [playFrom [playDuration]]"
13550     "\n\t\t:            [-speed Coeff] [-freeLook] [-lockLoop]"
13551     "\n\t\t:   -speed    playback speed (1.0 is normal speed)"
13552     "\n\t\t:   -freeLook skip camera animations"
13553     "\n\t\t:   -lockLoop disable any interactions"
13554     "\n\t\t:"
13555     "\n\t\t: Animation definition:"
13556     "\n\t\t:  vanim Name/sub/name [-clear] [-delete]"
13557     "\n\t\t:        [start TimeSec] [duration TimeSec]"
13558     "\n\t\t:"
13559     "\n\t\t: Animation name defined in path-style (anim/name or anim.name)"
13560     "\n\t\t: specifies nested animations."
13561     "\n\t\t: There is no syntax to explicitly add new animation,"
13562     "\n\t\t: and all non-existing animations within the name will be"
13563     "\n\t\t: implicitly created on first use (including parents)."
13564     "\n\t\t:"
13565     "\n\t\t: Each animation might define the SINGLE action (see below),"
13566     "\n\t\t: like camera transition, object transformation or custom callback."
13567     "\n\t\t: Child animations can be used for defining concurrent actions."
13568     "\n\t\t:"
13569     "\n\t\t: Camera animation:"
13570     "\n\t\t:  vanim name -view [-eye1 X Y Z] [-eye2 X Y Z]"
13571     "\n\t\t:                   [-at1  X Y Z] [-at2  X Y Z]"
13572     "\n\t\t:                   [-up1  X Y Z] [-up2  X Y Z]"
13573     "\n\t\t:                   [-scale1 Scale] [-scale2 Scale]"
13574     "\n\t\t:   -eyeX   camera Eye positions pair (start and end)"
13575     "\n\t\t:   -atX    camera Center positions pair"
13576     "\n\t\t:   -upX    camera Up directions pair"
13577     "\n\t\t:   -scaleX camera Scale factors pair"
13578     "\n\t\t: Object animation:"
13579     "\n\t\t:  vanim name -object [-loc1 X Y Z] [-loc2 X Y Z]"
13580     "\n\t\t:                     [-rot1 QX QY QZ QW] [-rot2 QX QY QZ QW]"
13581     "\n\t\t:                     [-scale1 Scale] [-scale2 Scale]"
13582     "\n\t\t:   -locX   object Location points pair (translation)"
13583     "\n\t\t:   -rotX   object Orientations pair (quaternions)"
13584     "\n\t\t:   -scaleX object Scale factors pair (quaternions)"
13585     "\n\t\t: Custom callback:"
13586     "\n\t\t:  vanim name -invoke \"Command Arg1 Arg2 %Pts %LocalPts %Normalized ArgN\""
13587     "\n\t\t:   %Pts        overall animation presentation timestamp"
13588     "\n\t\t:   %LocalPts   local animation timestamp"
13589     "\n\t\t:   %Normalized local animation normalized value in range 0..1"
13590     "\n\t\t:"
13591     "\n\t\t: Video recording:"
13592     "\n\t\t:  vanim name -record FileName [Width Height] [-fps FrameRate=24]"
13593     "\n\t\t:             [-format Format] [-vcodec Codec] [-pix_fmt PixelFormat]"
13594     "\n\t\t:             [-crf Value] [-preset Preset]"
13595     "\n\t\t:   -fps     video framerate"
13596     "\n\t\t:   -format  file format, container (matroska, etc.)"
13597     "\n\t\t:   -vcodec  video codec identifier (ffv1, mjpeg, etc.)"
13598     "\n\t\t:   -pix_fmt image pixel format (yuv420p, rgb24, etc.)"
13599     "\n\t\t:   -crf     constant rate factor (specific to codec)"
13600     "\n\t\t:   -preset  codec parameters preset (specific to codec)"
13601     __FILE__, VAnimation, group);
13602
13603   theCommands.Add("vchangeselected",
13604     "vchangeselected shape"
13605     "- adds to shape to selection or remove one from it",
13606                 __FILE__, VChangeSelected, group);
13607   theCommands.Add ("vnbselected",
13608     "vnbselected"
13609     "\n\t\t: Returns number of selected objects", __FILE__, VNbSelected, group);
13610   theCommands.Add ("vcamera",
13611               "vcamera [PrsName] [-ortho] [-projtype]"
13612       "\n\t\t:         [-persp]"
13613       "\n\t\t:         [-fovy   [Angle]] [-distance [Distance]]"
13614       "\n\t\t:         [-stereo] [-leftEye] [-rightEye]"
13615       "\n\t\t:         [-iod [Distance]] [-iodType    [absolute|relative]]"
13616       "\n\t\t:         [-zfocus [Value]] [-zfocusType [absolute|relative]]"
13617       "\n\t\t: Manages camera parameters."
13618       "\n\t\t: Displays frustum when presntation name PrsName is specified."
13619       "\n\t\t: Prints current value when option called without argument."
13620       "\n\t\t: Orthographic camera:"
13621       "\n\t\t:   -ortho      activate orthographic projection"
13622       "\n\t\t: Perspective camera:"
13623       "\n\t\t:   -persp      activate perspective  projection (mono)"
13624       "\n\t\t:   -fovy       field of view in y axis, in degrees"
13625       "\n\t\t:   -distance   distance of eye from camera center"
13626       "\n\t\t: Stereoscopic camera:"
13627       "\n\t\t:   -stereo     perspective  projection (stereo)"
13628       "\n\t\t:   -leftEye    perspective  projection (left  eye)"
13629       "\n\t\t:   -rightEye   perspective  projection (right eye)"
13630       "\n\t\t:   -iod        intraocular distance value"
13631       "\n\t\t:   -iodType    distance type, absolute or relative"
13632       "\n\t\t:   -zfocus     stereographic focus value"
13633       "\n\t\t:   -zfocusType focus type, absolute or relative",
13634     __FILE__, VCamera, group);
13635   theCommands.Add ("vautozfit", "command to enable or disable automatic z-range adjusting\n"
13636     "- vautozfit [on={1|0}] [scale]\n"
13637     "    Prints or changes parameters of automatic z-fit mode:\n"
13638     "   \"on\" - turns automatic z-fit on or off\n"
13639     "   \"scale\" - specifies factor to scale computed z range.\n",
13640     __FILE__, VAutoZFit, group);
13641   theCommands.Add ("vzrange", "command to manually access znear and zfar values\n"
13642     "   vzrange                - without parameters shows current values\n"
13643     "   vzrange [znear] [zfar] - applies provided values to view",
13644     __FILE__,VZRange, group);
13645   theCommands.Add ("vpurgedisplay",
13646     "vpurgedisplay"
13647     "- removes structures which don't belong to objects displayed in neutral point",
13648     __FILE__, VPurgeDisplay, group);
13649   theCommands.Add("vsetviewsize",
13650     "vsetviewsize size",
13651     __FILE__,VSetViewSize,group);
13652   theCommands.Add("vmoveview",
13653     "vmoveview Dx Dy Dz [Start = 1|0]",
13654     __FILE__,VMoveView,group);
13655   theCommands.Add("vtranslateview",
13656     "vtranslateview Dx Dy Dz [Start = 1|0)]",
13657     __FILE__,VTranslateView,group);
13658   theCommands.Add("vturnview",
13659     "vturnview Ax Ay Az [Start = 1|0]",
13660     __FILE__,VTurnView,group);
13661   theCommands.Add("vtextureenv",
13662     "Enables or disables environment mapping in the 3D view, loading the texture from the given standard "
13663     "or user-defined file and optionally applying texture mapping parameters\n"
13664     "                  Usage:\n"
13665     "                  vtextureenv off - disables environment mapping\n"
13666     "                  vtextureenv on {std_texture|texture_file_name} [rep mod flt ss st ts tt rot] - enables environment mapping\n"
13667     "                              std_texture = (0..7)\n"
13668     "                              rep         = {clamp|repeat}\n"
13669     "                              mod         = {decal|modulate}\n"
13670     "                              flt         = {nearest|bilinear|trilinear}\n"
13671     "                              ss, st      - scale factors for s and t texture coordinates\n"
13672     "                              ts, tt      - translation for s and t texture coordinates\n"
13673     "                              rot         - texture rotation angle in degrees",
13674     __FILE__, VTextureEnv, group);
13675   theCommands.Add("vhlr",
13676             "vhlr {on|off} [-showHidden={1|0}] [-algoType={algo|polyAlgo}] [-noupdate]"
13677       "\n\t\t: Hidden Line Removal algorithm."
13678       "\n\t\t:   -showHidden if set ON, hidden lines are drawn as dotted ones"
13679       "\n\t\t:   -algoType   type of HLR algorithm.\n",
13680     __FILE__,VHLR,group);
13681   theCommands.Add("vhlrtype",
13682               "vhlrtype {algo|polyAlgo} [shape_1 ... shape_n] [-noupdate]"
13683       "\n\t\t: Changes the type of HLR algorithm using for shapes:"
13684       "\n\t\t:   'algo' - exact HLR algorithm is applied"
13685       "\n\t\t:   'polyAlgo' - polygonal HLR algorithm is applied"
13686       "\n\t\t: If shapes are not given - option is applied to all shapes in the view",
13687     __FILE__,VHLRType,group);
13688   theCommands.Add("vclipplane",
13689               "vclipplane planeName [{0|1}]"
13690       "\n\t\t:   [-equation1 A B C D]"
13691       "\n\t\t:   [-equation2 A B C D]"
13692       "\n\t\t:   [-boxInterior MinX MinY MinZ MaxX MaxY MaxZ]"
13693       "\n\t\t:   [-set|-unset|-setOverrideGlobal [objects|views]]"
13694       "\n\t\t:   [-maxPlanes]"
13695       "\n\t\t:   [-capping {0|1}]"
13696       "\n\t\t:     [-color R G B] [-transparency Value] [-hatch {on|off|ID}]"
13697       "\n\t\t:     [-texName Texture] [-texScale SX SY] [-texOrigin TX TY]"
13698       "\n\t\t:       [-texRotate Angle]"
13699       "\n\t\t:     [-useObjMaterial {0|1}] [-useObjTexture {0|1}]"
13700       "\n\t\t:       [-useObjShader {0|1}]"
13701       "\n\t\t: Clipping planes management:"
13702       "\n\t\t:   -maxPlanes   print plane limit for view"
13703       "\n\t\t:   -delete      delete plane with given name"
13704       "\n\t\t:   {off|on|0|1} turn clipping on/off"
13705       "\n\t\t:   -set|-unset  set/unset plane for Object or View list;"
13706       "\n\t\t:                applied to active View when list is omitted"
13707       "\n\t\t:   -equation A B C D change plane equation"
13708       "\n\t\t:   -clone SourcePlane NewPlane clone the plane definition."
13709       "\n\t\t: Capping options:"
13710       "\n\t\t:   -capping {off|on|0|1} turn capping on/off"
13711       "\n\t\t:   -color R G B          set capping color"
13712       "\n\t\t:   -transparency Value   set capping transparency 0..1"
13713       "\n\t\t:   -texName Texture      set capping texture"
13714       "\n\t\t:   -texScale SX SY       set capping tex scale"
13715       "\n\t\t:   -texOrigin TX TY      set capping tex origin"
13716       "\n\t\t:   -texRotate Angle      set capping tex rotation"
13717       "\n\t\t:   -hatch {on|off|ID}    set capping hatching mask"
13718       "\n\t\t:   -useObjMaterial {off|on|0|1} use material of clipped object"
13719       "\n\t\t:   -useObjTexture  {off|on|0|1} use texture of clipped object"
13720       "\n\t\t:   -useObjShader   {off|on|0|1} use shader program of object",
13721       __FILE__, VClipPlane, group);
13722   theCommands.Add("vdefaults",
13723                "vdefaults [-absDefl value]"
13724        "\n\t\t:           [-devCoeff value]"
13725        "\n\t\t:           [-angDefl value]"
13726        "\n\t\t:           [-autoTriang {off/on | 0/1}]"
13727     , __FILE__, VDefaults, group);
13728   theCommands.Add("vlight",
13729     "tool to manage light sources, without arguments shows list of lights."
13730     "\n    Main commands: "
13731     "\n      '-clear' to clear lights"
13732     "\n      '-{def}aults' to load deafault lights"
13733     "\n      '-add' <type> to add any light source"
13734     "\n          where <type> is one of {amb}ient|directional|{spot}light|positional"
13735     "\n      'change' <lightId> to edit light source with specified lightId"
13736     "\n\n      In addition to 'add' and 'change' commands you can use light parameters:"
13737     "\n        -layer Id"
13738     "\n        -{pos}ition X Y Z"
13739     "\n        -{dir}ection X Y Z (for directional light or for spotlight)"
13740     "\n        -color colorName"
13741     "\n        -{head}light 0|1"
13742     "\n        -{sm}oothness value"
13743     "\n        -{int}ensity value"
13744     "\n        -{constAtten}uation value"
13745     "\n        -{linearAtten}uation value"
13746     "\n        -angle angleDeg"
13747     "\n        -{spotexp}onent value"
13748     "\n        -local|-global"
13749     "\n\n        example: vlight -add positional -head 1 -pos 0 1 1 -color red"
13750     "\n        example: vlight -change 0 -direction 0 -1 0 -linearAttenuation 0.2",
13751     __FILE__, VLight, group);
13752   theCommands.Add("vraytrace",
13753             "vraytrace [0|1]"
13754     "\n\t\t: Turns on/off ray-tracing renderer."
13755     "\n\t\t:   'vraytrace 0' alias for 'vrenderparams -raster'."
13756     "\n\t\t:   'vraytrace 1' alias for 'vrenderparams -rayTrace'.",
13757     __FILE__, VRenderParams, group);
13758   theCommands.Add("vrenderparams",
13759     "\n    Manages rendering parameters: "
13760     "\n      '-raster'                   Disables GPU ray-tracing"
13761     "\n      '-msaa         0..4'        Specifies number of samples for MSAA"
13762     "\n      '-lineFeather  > 0'         Sets line feather factor"
13763     "\n      '-oit          off|0.0-1.0' Enables/disables OIT and sets depth weight factor"
13764     "\n      '-depthPrePass on|off'      Enables/disables depth pre-pass"
13765     "\n      '-alphatocoverage on|off'   Enables/disables alpha to coverage (needs MSAA)"
13766     "\n      '-rendScale    value        Rendering resolution scale factor"
13767     "\n      '-rayTrace'                 Enables  GPU ray-tracing"
13768     "\n      '-rayDepth     0..10'       Defines maximum ray-tracing depth"
13769     "\n      '-shadows      on|off'      Enables/disables shadows rendering"
13770     "\n      '-reflections  on|off'      Enables/disables specular reflections"
13771     "\n      '-fsaa         on|off'      Enables/disables adaptive anti-aliasing"
13772     "\n      '-gleam        on|off'      Enables/disables transparency shadow effects"
13773     "\n      '-gi           on|off'      Enables/disables global illumination effects"
13774     "\n      '-brng         on|off'      Enables/disables blocked RNG (fast coherent PT)"
13775     "\n      '-env          on|off'      Enables/disables environment map background"
13776     "\n      '-twoside      on|off'      Enables/disables two-sided BSDF models (PT mode)"
13777     "\n      '-iss          on|off'      Enables/disables adaptive screen sampling (PT mode)"
13778     "\n      '-issd         on|off'      Shows screen sampling distribution in ISS mode"
13779     "\n      '-maxrad       > 0.0'       Value used for clamping radiance estimation (PT mode)"
13780     "\n      '-tileSize     1..4096'     Specifies   size of screen tiles in ISS mode (32 by default)"
13781     "\n      '-nbtiles      64..1024'    Specifies number of screen tiles per Redraw in ISS mode (256 by default)"
13782     "\n      '-rebuildGlsl  on|off'      Rebuild Ray-Tracing GLSL programs (for debugging)"
13783     "\n      '-shadingModel model'       Controls shading model from enumeration"
13784     "\n                                  color, flat, gouraud, phong"
13785     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
13786     "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
13787     "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
13788     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
13789     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
13790     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
13791     "\n      '-perfCounters none|fps|cpu|layers|structures|groups|arrays|triagles|points"
13792     "\n      '              |gpuMem|frameTime|basic|extended|full|nofps|skipImmediate'"
13793     "\n                                  Show/hide performance counters (flags can be combined)"
13794     "\n      '-perfUpdateInterval nbSeconds' Performance counters update interval"
13795     "\n      '-perfChart    nbFrames'    Show frame timers chart limited by specified number of frames"
13796     "\n      '-perfChartMax seconds'     Maximum time in seconds with the chart"
13797     "\n      '-frustumCulling on|off|noupdate' Enable/disable objects frustum clipping or"
13798     "\n                                        set state to check structures culled previously."
13799     "\n    Unlike vcaps, these parameters dramatically change visual properties."
13800     "\n    Command is intended to control presentation quality depending on"
13801     "\n    hardware capabilities and performance.",
13802     __FILE__, VRenderParams, group);
13803   theCommands.Add("vstatprofiler",
13804     "\n vstatprofiler [fps|cpu|allLayers|layers|allstructures|structures|groups"
13805     "\n                |allArrays|fillArrays|lineArrays|pointArrays|textArrays"
13806     "\n                |triagles|points|geomMem|textureMem|frameMem"
13807     "\n                |elapsedFrame|cpuFrameAverage|cpuPickingAverage|cpuCullingAverage|cpuDynAverage"
13808     "\n                |cpuFrameMax|cpuPickingMax|cpuCullingMax|cpuDynMax]"
13809     "\n                [-noredraw]"
13810     "\n\t\t: Prints rendering statistics."
13811     "\n\t\t:   If there are some parameters - print corresponding statistic counters values,"
13812     "\n\t\t:   else - print all performance counters set previously."
13813     "\n\t\t:   '-noredraw' Flag to avoid additional redraw call and use already collected values.\n",
13814     __FILE__, VStatProfiler, group);
13815   theCommands.Add ("vplace",
13816             "vplace dx dy"
13817     "\n\t\t: Places the point (in pixels) at the center of the window",
13818     __FILE__, VPlace, group);
13819   theCommands.Add("vxrotate",
13820     "vxrotate",
13821     __FILE__,VXRotate,group);
13822
13823     theCommands.Add("vmanipulator",
13824       "\n    vmanipulator Name [-attach AISObject | -detach | ...]"
13825       "\n    tool to create and manage AIS manipulators."
13826       "\n    Options: "
13827       "\n      '-attach AISObject'                 attach manipulator to AISObject"
13828       "\n      '-adjustPosition {0|1}'             adjust position when attaching"
13829       "\n      '-adjustSize     {0|1}'             adjust size when attaching"
13830       "\n      '-enableModes    {0|1}'             enable modes when attaching"
13831       "\n      '-view  {active | [name of view]}'  display manipulator only in defined view,"
13832       "\n                                          by default it is displayed in all views of the current viewer"
13833       "\n      '-detach'                           detach manipulator"
13834       "\n      '-startTransform mouse_x mouse_y' - invoke start of transformation"
13835       "\n      '-transform      mouse_x mouse_y' - invoke transformation"
13836       "\n      '-stopTransform  [abort]'         - invoke stop of transformation"
13837       "\n      '-move x y z'                     - move attached object"
13838       "\n      '-rotate x y z dx dy dz angle'    - rotate attached object"
13839       "\n      '-scale factor'                   - scale attached object"
13840       "\n      '-autoActivate      {0|1}'        - set activation on detection"
13841       "\n      '-followTranslation {0|1}'        - set following translation transform"
13842       "\n      '-followRotation    {0|1}'        - set following rotation transform"
13843       "\n      '-followDragging    {0|1}'        - set following dragging transform"
13844       "\n      '-gap value'                      - set gap between sub-parts"
13845       "\n      '-part axis mode    {0|1}'        - set visual part"
13846       "\n      '-parts axis mode   {0|1}'        - set visual part"
13847       "\n      '-pos x y z [nx ny nz [xx xy xz]' - set position of manipulator"
13848       "\n      '-size value'                     - set size of manipulator"
13849       "\n      '-zoomable {0|1}'                 - set zoom persistence",
13850     __FILE__, VManipulator, group);
13851
13852   theCommands.Add("vselprops",
13853     "\n    vselprops [dynHighlight|localDynHighlight|selHighlight|localSelHighlight] [options]"
13854     "\n    Customizes selection and dynamic highlight parameters for the whole interactive context:"
13855     "\n    -autoActivate {0|1}     : disables|enables default computation and activation of global selection mode"
13856     "\n    -autoHighlight {0|1}    : disables|enables automatic highlighting in 3D Viewer"
13857     "\n    -highlightSelected {0|1}: disables|enables highlighting of detected object in selected state"
13858     "\n    -pickStrategy {first|topmost} : defines picking strategy"
13859     "\n                            'first'   to pick first acceptable (default)"
13860     "\n                            'topmost' to pick only topmost (and nothing, if topmost is rejected by filters)"
13861     "\n    -pixTol    value        : sets up pixel tolerance"
13862     "\n    -dispMode  dispMode     : sets display mode for highlighting"
13863     "\n    -layer     ZLayer       : sets ZLayer for highlighting"
13864     "\n    -color     {name|r g b} : sets highlight color"
13865     "\n    -transp    value        : sets transparency coefficient for highlight"
13866     "\n    -material  material     : sets highlight material"
13867     "\n    -print                  : prints current state of all mentioned parameters",
13868     __FILE__, VSelectionProperties, group);
13869   theCommands.Add ("vhighlightselected",
13870                    "vhighlightselected [0|1]: alias for vselprops -highlightSelected.\n",
13871                    __FILE__, VSelectionProperties, group);
13872
13873   theCommands.Add ("vseldump",
13874                    "vseldump file -type {depth|unnormDepth|object|owner|selMode|entity}=depth -pickedIndex Index=1"
13875                    "\n\t\t: Generate an image based on detection results:"
13876                    "\n\t\t:   depth       normalized depth values"
13877                    "\n\t\t:   unnormDepth unnormalized depth values"
13878                    "\n\t\t:   object      color of detected object"
13879                    "\n\t\t:   owner       color of detected owner"
13880                    "\n\t\t:   selMode     color of selection mode"
13881                    "\n\t\t:   entity      color of etected entity",
13882                    __FILE__, VDumpSelectionImage, group);
13883 }
13884