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
6 // This file is part of Open CASCADE Technology software library.
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.
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
17 #include <OpenGl_GlCore20.hxx>
18 #include <ViewerTest.hxx>
20 #include <AIS_AnimationCamera.hxx>
21 #include <AIS_AnimationObject.hxx>
22 #include <AIS_CameraFrustum.hxx>
23 #include <AIS_ColorScale.hxx>
24 #include <AIS_InteractiveContext.hxx>
25 #include <AIS_ListOfInteractive.hxx>
26 #include <AIS_ListIteratorOfListOfInteractive.hxx>
27 #include <AIS_Manipulator.hxx>
28 #include <AIS_ViewCube.hxx>
29 #include <AIS_Shape.hxx>
30 #include <Aspect_DisplayConnection.hxx>
31 #include <Aspect_Grid.hxx>
32 #include <Aspect_TypeOfLine.hxx>
34 #include <Draw_Appli.hxx>
35 #include <Draw_Interpretor.hxx>
36 #include <Draw_ProgressIndicator.hxx>
40 #include <Graphic3d_ArrayOfPolylines.hxx>
41 #include <Graphic3d_AspectFillArea3d.hxx>
42 #include <Graphic3d_AspectMarker3d.hxx>
43 #include <Graphic3d_ClipPlane.hxx>
44 #include <Graphic3d_CubeMapPacked.hxx>
45 #include <Graphic3d_CubeMapSeparate.hxx>
46 #include <Graphic3d_GraduatedTrihedron.hxx>
47 #include <Graphic3d_NameOfTextureEnv.hxx>
48 #include <Graphic3d_Texture2Dmanual.hxx>
49 #include <Graphic3d_TextureEnv.hxx>
50 #include <Graphic3d_TextureParams.hxx>
51 #include <Graphic3d_TypeOfTextureFilter.hxx>
52 #include <Image_AlienPixMap.hxx>
53 #include <Image_Diff.hxx>
54 #include <Image_VideoRecorder.hxx>
55 #include <Message_ProgressSentry.hxx>
56 #include <NCollection_DataMap.hxx>
57 #include <NCollection_List.hxx>
58 #include <NCollection_Vector.hxx>
60 #include <OSD_Timer.hxx>
61 #include <OpenGl_GraphicDriver.hxx>
62 #include <Prs3d_ShadingAspect.hxx>
63 #include <Prs3d_Drawer.hxx>
64 #include <Prs3d_LineAspect.hxx>
65 #include <Prs3d_Root.hxx>
66 #include <Prs3d_Text.hxx>
67 #include <Select3D_SensitivePrimitiveArray.hxx>
68 #include <TColStd_HSequenceOfAsciiString.hxx>
69 #include <TColStd_SequenceOfInteger.hxx>
70 #include <TColStd_HSequenceOfReal.hxx>
71 #include <TColgp_Array1OfPnt2d.hxx>
72 #include <TColStd_MapOfAsciiString.hxx>
73 #include <ViewerTest_AutoUpdater.hxx>
74 #include <ViewerTest_EventManager.hxx>
75 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
76 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
77 #include <ViewerTest_CmdParser.hxx>
78 #include <ViewerTest_V3dView.hxx>
79 #include <V3d_AmbientLight.hxx>
80 #include <V3d_DirectionalLight.hxx>
81 #include <V3d_PositionalLight.hxx>
82 #include <V3d_SpotLight.hxx>
89 #include <WNT_WClass.hxx>
90 #include <WNT_Window.hxx>
91 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
92 #include <Cocoa_Window.hxx>
94 #include <Xw_Window.hxx>
95 #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
96 #include <X11/Xutil.h>
100 //==============================================================================
101 // VIEWER GLOBAL VARIABLES
102 //==============================================================================
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
111 static Handle(WNT_Window)& VT_GetWindow() {
112 static Handle(WNT_Window) WNTWin;
115 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
116 static Handle(Cocoa_Window)& VT_GetWindow()
118 static Handle(Cocoa_Window) aWindow;
121 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
122 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
125 static Handle(Xw_Window)& VT_GetWindow(){
126 static Handle(Xw_Window) XWWin;
130 static void VProcessEvents(ClientData,int);
133 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
135 static Handle(Aspect_DisplayConnection) aDisplayConnection;
136 return aDisplayConnection;
139 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
141 GetDisplayConnection() = theDisplayConnection;
144 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
145 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)> ViewerTest_myContexts;
146 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
147 static OpenGl_Caps ViewerTest_myDefaultCaps;
149 static void OSWindowSetup();
153 Quantity_Color FlatColor;
154 Quantity_Color GradientColor1;
155 Quantity_Color GradientColor2;
156 Aspect_GradientFillMethod FillMethod;
157 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
159 //==============================================================================
160 // EVENT GLOBAL VARIABLES
161 //==============================================================================
163 Standard_Boolean TheIsAnimating = Standard_False;
168 //! Checks if some set is a subset of other set
169 //! @tparam TheSuperSet the type of the superset
170 //! @tparam TheSubSet the type of the subset
171 //! @param theSuperSet the superset
172 //! @param theSubSet the subset to be checked
173 //! @return true if the superset includes subset, or false otherwise
174 template <typename TheSuperSet, typename TheSubSet>
175 static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
177 return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
180 //! A variable set of keys for command-line options.
181 //! It includes a set of mandatory keys and a set of all possible keys.
182 class CommandOptionKeyVariableSet
185 //! Default constructor
186 CommandOptionKeyVariableSet()
191 //! @param theMandatoryKeySet the set of the mandatory option keys
192 //! @param theAdditionalKeySet the set of additional options that could be omitted
193 CommandOptionKeyVariableSet (
194 const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
195 const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
196 : myMandatoryKeySet (theMandatoryKeySet)
198 std::set_union (theMandatoryKeySet.begin(),
199 theMandatoryKeySet.end(),
200 theAdditionalKeySet.begin(),
201 theAdditionalKeySet.end(),
202 std::inserter (myFullKeySet, myFullKeySet.begin()));
205 //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
206 //! and be contained in the full key set)
207 //! @param theCheckedKeySet the set of option keys to be checked
208 bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
210 return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
214 //! A set of mandatory command-line option keys
215 ViewerTest_CommandOptionKeySet myMandatoryKeySet;
217 //! A full set of command-line option keys (includes mandatory and additional option keys)
218 ViewerTest_CommandOptionKeySet myFullKeySet;
221 //! Gets some code by its name
222 //! @tparam TheCode the type of a code to be found
223 //! @param theCodeNameMap the map from code names to codes
224 //! @param theCodeName the name of a code to be found
225 //! @param theCode the code to be found
226 //! @return true if a code is found, or false otherwise
227 template <typename TheCode>
228 static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
229 TCollection_AsciiString theCodeName,
232 theCodeName.LowerCase();
233 const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
235 if (aCodeIterator == theCodeNameMap.end())
239 theCode = aCodeIterator->second;
243 // Defines possible commands related to background changing
244 enum BackgroundCommand
246 BackgroundCommand_Main, //!< The main command that manages other commands through options
247 BackgroundCommand_Image, //!< Sets an image as a background
248 BackgroundCommand_ImageMode, //!< Changes a background image mode
249 BackgroundCommand_Gradient, //!< Sets a gradient as a background
250 BackgroundCommand_GradientMode, //!< Changes a background gradient mode
251 BackgroundCommand_Color, //!< Fills background with a specified color
252 BackgroundCommand_Default //!< Sets the background default color or gradient
255 //! Map from background command names to its codes
256 typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
258 //! Creates a map from background command names to its codes
259 //! @return a map from background command names to its codes
260 static BackgroundCommandNameMap createBackgroundCommandNameMap()
262 BackgroundCommandNameMap aBackgroundCommandNameMap;
263 aBackgroundCommandNameMap["vbackground"] = BackgroundCommand_Main;
264 aBackgroundCommandNameMap["vsetbg"] = BackgroundCommand_Image;
265 aBackgroundCommandNameMap["vsetbgmode"] = BackgroundCommand_ImageMode;
266 aBackgroundCommandNameMap["vsetgradientbg"] = BackgroundCommand_Gradient;
267 aBackgroundCommandNameMap["vsetgrbgmode"] = BackgroundCommand_GradientMode;
268 aBackgroundCommandNameMap["vsetcolorbg"] = BackgroundCommand_Color;
269 aBackgroundCommandNameMap["vsetdefaultbg"] = BackgroundCommand_Default;
270 return aBackgroundCommandNameMap;
273 //! Gets a background command by its name
274 //! @param theBackgroundCommandName the name of the background command
275 //! @param theBackgroundCommand the background command to be found
276 //! @return true if a background command is found, or false otherwise
277 static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
278 BackgroundCommand& theBackgroundCommand)
280 static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
281 return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
284 //! Map from background image fill method names to its codes
285 typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
287 //! Creates a map from background image fill method names to its codes
288 //! @return a map from background image fill method names to its codes
289 static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
291 BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
292 aBackgroundImageFillMethodNameMap["none"] = Aspect_FM_NONE;
293 aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
294 aBackgroundImageFillMethodNameMap["tiled"] = Aspect_FM_TILED;
295 aBackgroundImageFillMethodNameMap["stretch"] = Aspect_FM_STRETCH;
296 return aBackgroundImageFillMethodNameMap;
299 //! Gets a background image fill method by its name
300 //! @param theBackgroundImageFillMethodName the name of the background image fill method
301 //! @param theBackgroundImageFillMethod the background image fill method to be found
302 //! @return true if a background image fill method is found, or false otherwise
303 static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
304 Aspect_FillMethod& theBackgroundImageFillMethod)
306 static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
307 createBackgroundImageFillMethodNameMap();
308 return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
309 theBackgroundImageFillMethodName,
310 theBackgroundImageFillMethod);
313 //! Map from background gradient fill method names to its codes
314 typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
316 //! Creates a map from background gradient fill method names to its codes
317 //! @return a map from background gradient fill method names to its codes
318 static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
320 BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
321 aBackgroundGradientFillMethodNameMap["none"] = Aspect_GFM_NONE;
322 aBackgroundGradientFillMethodNameMap["hor"] = Aspect_GFM_HOR;
323 aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
324 aBackgroundGradientFillMethodNameMap["ver"] = Aspect_GFM_VER;
325 aBackgroundGradientFillMethodNameMap["vertical"] = Aspect_GFM_VER;
326 aBackgroundGradientFillMethodNameMap["diag1"] = Aspect_GFM_DIAG1;
327 aBackgroundGradientFillMethodNameMap["diagonal1"] = Aspect_GFM_DIAG1;
328 aBackgroundGradientFillMethodNameMap["diag2"] = Aspect_GFM_DIAG2;
329 aBackgroundGradientFillMethodNameMap["diagonal2"] = Aspect_GFM_DIAG2;
330 aBackgroundGradientFillMethodNameMap["corner1"] = Aspect_GFM_CORNER1;
331 aBackgroundGradientFillMethodNameMap["corner2"] = Aspect_GFM_CORNER2;
332 aBackgroundGradientFillMethodNameMap["corner3"] = Aspect_GFM_CORNER3;
333 aBackgroundGradientFillMethodNameMap["corner4"] = Aspect_GFM_CORNER4;
334 return aBackgroundGradientFillMethodNameMap;
337 //! Gets a gradient fill method by its name
338 //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
339 //! @param theBackgroundGradientFillMethod the gradient fill method to be found
340 //! @return true if a gradient fill method is found, or false otherwise
341 static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
342 Aspect_GradientFillMethod& theBackgroundGradientFillMethod)
344 static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
345 createBackgroundGradientFillMethodNameMap();
346 return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
347 theBackgroundGradientFillMethodName,
348 theBackgroundGradientFillMethod);
351 //! Changes the background in accordance with passed command line options
352 class BackgroundChanger
355 //! Constructor. Prepares the command parser
358 prepareCommandParser();
361 //! Processes the command line and changes the background
362 //! @param theDrawInterpretor the interpreter of the Draw Harness application
363 //! @param theNumberOfCommandLineArguments the number of passed command line arguments
364 //! @param theCommandLineArguments the array of command line arguments
365 bool ProcessCommandLine (Draw_Interpretor& theDrawInterpretor,
366 const Standard_Integer theNumberOfCommandLineArguments,
367 const char* const* const theCommandLineArguments)
369 const char* const aBackgroundCommandName = theCommandLineArguments[0];
370 BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
371 if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
375 addCommandDescription (aBackgroundCommand);
376 myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
377 return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
381 //! The type of functions that are able to set gradient background filling
382 typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
383 const Quantity_Color& /* theColor2 */,
384 const Aspect_GradientFillMethod /* theGradientMode */);
386 //! The type of functions that are able to fill a background with a specific color
387 typedef void SetColorFunction (const Quantity_Color& /* theColor */);
389 //! the command parser used to parse command line options and its arguments
390 ViewerTest_CmdParser myCommandParser;
392 //! the option key for the command that sets an image as a background
393 ViewerTest_CommandOptionKey myImageOptionKey;
395 //! the option key for the command that sets a background image fill type
396 ViewerTest_CommandOptionKey myImageModeOptionKey;
398 //! the option key for the command that sets a gradient filling for the background
399 ViewerTest_CommandOptionKey myGradientOptionKey;
401 //! the option key for the command that sets a background gradient filling method
402 ViewerTest_CommandOptionKey myGradientModeOptionKey;
404 //! the option key for the command that fills background with a specific color
405 ViewerTest_CommandOptionKey myColorOptionKey;
407 //! the option key for the command that sets default background gradient or color
408 ViewerTest_CommandOptionKey myDefaultOptionKey;
410 //! the option key for the command that sets an environment cubemap as a background
411 ViewerTest_CommandOptionKey myCubeMapOptionKey;
413 //! the option key for the command that defines order of tiles in one image packed cubemap
414 ViewerTest_CommandOptionKey myCubeMapOrderOptionKey;
416 //! the option key for the command that sets inversion of Z axis for background cubemap
417 ViewerTest_CommandOptionKey myCubeMapInvertedZOptionKey;
419 //! the option key for the command that allows skip IBL map generation
420 ViewerTest_CommandOptionKey myCubeMapDoNotGenPBREnvOptionKey;
422 //! the variable set of options that are allowed for the old scenario (without any option passed)
423 CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
425 //! the variable set of options that are allowed for setting an environment cubemap as background
426 CommandOptionKeyVariableSet myCubeMapOptionVariableSet;
428 //! the variable set of options that are allowed for setting an image as a background
429 CommandOptionKeyVariableSet myImageOptionVariableSet;
431 //! the variable set of options that are allowed for setting a background image fill type
432 CommandOptionKeyVariableSet myImageModeOptionVariableSet;
434 //! the variable set of options that are allowed for setting a gradient filling for the background
435 CommandOptionKeyVariableSet myGradientOptionVariableSet;
437 //! the variable set of options that are allowed for setting a background gradient filling method
438 CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
440 //! the variable set of options that are allowed for filling a background with a specific color
441 CommandOptionKeyVariableSet myColorOptionVariableSet;
443 //! the variable set of options that are allowed for setting a default background gradient
444 CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
446 //! the variable set of options that are allowed for setting a default background color
447 CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
449 //! the variable set of options that are allowed for printing help
450 CommandOptionKeyVariableSet myHelpOptionVariableSet;
452 //! Adds options to command parser
453 void addOptionsToCommandParser()
455 myImageOptionKey = myCommandParser.AddOption ("imageFile|image|imgFile|img",
456 "filename of image used as background");
457 myImageModeOptionKey = myCommandParser.AddOption (
458 "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
459 myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
460 "sets background gradient starting and ending colors");
461 myGradientModeOptionKey =
462 myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
463 "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
464 "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
465 myColorOptionKey = myCommandParser.AddOption ("color|col", "background color");
466 myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
468 myCubeMapOptionKey = myCommandParser.AddOption ("cubemap|cmap|cm", "background cubemap");
469 myCubeMapOrderOptionKey = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
470 myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
471 "invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
472 myCubeMapDoNotGenPBREnvOptionKey = myCommandParser.AddOption ("nopbrenv", "whether IBL map generation should be skipped");
475 //! Creates option sets used to determine if a passed option set is valid or not
476 void createOptionSets()
478 ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
479 anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
480 myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
482 ViewerTest_CommandOptionKeySet aCubeMapOptionSet;
483 aCubeMapOptionSet.insert (myCubeMapOptionKey);
484 ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
485 aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
486 aCubeMapAdditionalOptionKeySet.insert (myCubeMapDoNotGenPBREnvOptionKey);
487 aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
488 myCubeMapOptionVariableSet = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
490 ViewerTest_CommandOptionKeySet anImageOptionSet;
491 anImageOptionSet.insert (myImageOptionKey);
492 ViewerTest_CommandOptionKeySet anImageModeOptionSet;
493 anImageModeOptionSet.insert (myImageModeOptionKey);
494 myImageOptionVariableSet = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
495 myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
497 ViewerTest_CommandOptionKeySet aGradientOptionSet;
498 aGradientOptionSet.insert (myGradientOptionKey);
499 ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
500 aGradientModeOptionSet.insert (myGradientModeOptionKey);
501 myGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
502 myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
504 ViewerTest_CommandOptionKeySet aColorOptionSet;
505 aColorOptionSet.insert (myColorOptionKey);
506 myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
508 aGradientOptionSet.insert (myDefaultOptionKey);
509 myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
510 aColorOptionSet.insert (myDefaultOptionKey);
511 myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
513 ViewerTest_CommandOptionKeySet aHelpOptionSet;
514 aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
515 myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
518 //! Prepares the command parser. Adds options and creates option sets used to determine
519 //! if a passed option set is valid or not
520 void prepareCommandParser()
522 addOptionsToCommandParser();
526 //! Adds a command description to the command parser
527 //! @param theBackgroundCommand the key of the command which description is added to the command parser
528 void addCommandDescription (const BackgroundCommand theBackgroundCommand)
530 std::string aDescription;
531 bool isMainCommand = false;
532 switch (theBackgroundCommand)
534 case BackgroundCommand_Main:
535 aDescription = "Command: vbackground (changes background or some background settings)";
536 isMainCommand = true;
538 case BackgroundCommand_Image:
539 aDescription = "Command: vsetbg (loads image as a background)";
541 case BackgroundCommand_ImageMode:
542 aDescription = "Command: vsetbgmode (changes background fill type)";
544 case BackgroundCommand_Gradient:
545 aDescription = "Command: vsetgradientbg (mounts gradient background)";
547 case BackgroundCommand_GradientMode:
548 aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
550 case BackgroundCommand_Color:
551 aDescription = "Command: vsetcolorbg (sets color background)";
553 case BackgroundCommand_Default:
554 aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
561 aDescription += "\nThis command is obsolete. Use vbackground instead.";
563 myCommandParser.SetDescription (aDescription);
566 //! Check if a viewer is needed to be initialized
567 //! @param theBackgroundCommand the key of the command that changes the background
568 //! @return true if processing was successful, or false otherwise
569 bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
571 const bool isMain = (theBackgroundCommand == BackgroundCommand_Main);
572 const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
573 const bool aViewerIsNotNeeded =
574 (theBackgroundCommand == BackgroundCommand_Default)
575 || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
576 || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
577 || myHelpOptionVariableSet.IsInSet (aUsedOptions);
578 return !aViewerIsNotNeeded;
581 //! Check if a viewer is initialized
582 //! @param theBackgroundCommandName the name of the command that changes the background
583 //! @param theDrawInterpretor the interpreter of the Draw Harness application
584 //! @return true if a viewer is initialized, or false otherwise
585 static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
586 Draw_Interpretor& theDrawInterpretor)
588 const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
589 if (anAISContext.IsNull())
591 theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
597 //! Processes command options
598 //! @param theBackgroundCommandName the name of the command that changes the background
599 //! @param theBackgroundCommand the key of the command that changes the background
600 //! @param theDrawInterpretor the interpreter of the Draw Harness application
601 //! @return true if processing was successful, or false otherwise
602 bool processCommandOptions (const char* const theBackgroundCommandName,
603 const BackgroundCommand theBackgroundCommand,
604 Draw_Interpretor& theDrawInterpretor) const
606 if (myCommandParser.HasNoOption())
608 return printHelp (theBackgroundCommandName, theDrawInterpretor);
610 if (checkViewerIsNeeded (theBackgroundCommand)
611 && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
615 if (myCommandParser.HasOnlyUnnamedOption())
617 return processUnnamedOption (theBackgroundCommand);
619 return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
622 //! Processes the unnamed option
623 //! @param theBackgroundCommand the key of the command that changes the background
624 //! @return true if processing was successful, or false otherwise
625 bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
627 switch (theBackgroundCommand)
629 case BackgroundCommand_Main:
631 case BackgroundCommand_Image:
632 return processImageUnnamedOption();
633 case BackgroundCommand_ImageMode:
634 return processImageModeUnnamedOption();
635 case BackgroundCommand_Gradient:
636 return processGradientUnnamedOption();
637 case BackgroundCommand_GradientMode:
638 return processGradientModeUnnamedOption();
639 case BackgroundCommand_Color:
640 return processColorUnnamedOption();
641 case BackgroundCommand_Default:
642 return processDefaultUnnamedOption();
648 //! Processes the image unnamed option
649 //! @return true if processing was successful, or false otherwise
650 bool processImageUnnamedOption() const
652 const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
653 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
654 if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
658 std::string anImageFileName;
659 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
663 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
664 if (aNumberOfImageUnnamedOptionArguments == 2)
666 std::string anImageModeString;
667 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
671 if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
676 setImage (anImageFileName.c_str(), anImageMode);
680 //! Processes the image mode unnamed option
681 //! @return true if processing was successful, or false otherwise
682 bool processImageModeUnnamedOption() const
684 return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
687 //! Processes the gradient unnamed option
688 //! @param theSetGradient the function used to set a background gradient filling
689 //! @return true if processing was successful, or false otherwise
690 bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
692 const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
693 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
694 if (aNumberOfGradientUnnamedOptionArguments < 2)
699 Standard_Integer anArgumentIndex = 0;
700 Quantity_Color aColor1;
701 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
705 if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
710 Quantity_Color aColor2;
711 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
715 if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
720 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
721 if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
723 std::string anGradientModeString;
725 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
727 anGradientModeString))
731 if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
737 if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
741 theSetGradient (aColor1, aColor2, aGradientMode);
745 //! Processes the gradient mode unnamed option
746 //! @return true if processing was successful, or false otherwise
747 bool processGradientModeUnnamedOption() const
749 return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
752 //! Processes the color unnamed option
753 //! @param theSetColor the function used to set a background color
754 //! @return true if processing was successful, or false otherwise
755 bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
757 return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
760 //! Processes the default back unnamed option
761 //! @return true if processing was successful, or false otherwise
762 bool processDefaultUnnamedOption() const
764 if (processGradientUnnamedOption (setDefaultGradient))
768 return processColorUnnamedOption (setDefaultColor);
771 //! Processes named options
772 //! @param theBackgroundCommandName the name of the command that changes the background
773 //! @param theBackgroundCommand the key of the command that changes the background
774 //! @param theDrawInterpretor the interpreter of the Draw Harness application
775 //! @return true if processing was successful, or false otherwise
776 bool processNamedOptions (const char* const theBackgroundCommandName,
777 const BackgroundCommand theBackgroundCommand,
778 Draw_Interpretor& theDrawInterpretor) const
780 const bool isMain = (theBackgroundCommand == BackgroundCommand_Main);
781 const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
782 if (myCubeMapOptionVariableSet.IsInSet (aUsedOptions) && isMain)
784 return processCubeMapOptionSet();
786 if (myImageOptionVariableSet.IsInSet (aUsedOptions)
787 && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
789 return processImageOptionSet();
791 if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
792 && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
794 return processImageModeOptionSet();
796 if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
797 && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
799 return processGradientOptionSet();
801 if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
802 && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
804 return processGradientModeOptionSet();
806 if (myColorOptionVariableSet.IsInSet (aUsedOptions)
807 && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
809 return processColorOptionSet();
811 if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
812 || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
813 && (theBackgroundCommand == BackgroundCommand_Default)))
815 return processDefaultGradientOptionSet();
817 if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
818 || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
820 return processDefaultColorOptionSet();
822 if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
824 return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
829 //! Process the cubemap option set in named and unnamed case.
830 //! @return true if processing was successful, or false otherwise
831 bool processCubeMapOptionSet() const
833 NCollection_Array1<TCollection_AsciiString> aFilePaths;
835 if (!processCubeMapOptions (aFilePaths))
840 Graphic3d_CubeMapOrder anOrder = Graphic3d_CubeMapOrder::Default();
842 if (myCommandParser.HasOption (myCubeMapOrderOptionKey))
844 if (!processCubeMapOrderOptions (anOrder))
850 bool aZIsInverted = false;
851 if (myCommandParser.HasOption (myCubeMapInvertedZOptionKey))
853 if (!processCubeMapInvertedZOptionSet())
860 bool aToGenPBREnv = true;
861 if (myCommandParser.HasOption (myCubeMapDoNotGenPBREnvOptionKey))
863 if (!processCubeMapDoNotGenPBREnvOptionSet())
867 aToGenPBREnv = false;
870 setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted, aToGenPBREnv);
874 //! Processes the image option set
875 //! @return true if processing was successful, or false otherwise
876 bool processImageOptionSet() const
878 std::string anImageFileName;
879 if (!processImageOption (anImageFileName))
883 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
884 if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
888 setImage (anImageFileName.c_str(), anImageMode);
892 //! Processes the image mode option set
893 //! @return true if processing was successful, or false otherwise
894 bool processImageModeOptionSet() const
896 return processImageModeOptionSet (myImageModeOptionKey);
899 //! Processes the image mode option set
900 //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
901 //! @return true if processing was successful, or false otherwise
902 bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
904 Aspect_FillMethod anImageMode = Aspect_FM_NONE;
905 if (!processImageModeOption (theImageModeOptionKey, anImageMode))
909 setImageMode (anImageMode);
913 //! Processes the gradient option set
914 //! @param theSetGradient the function used to set a background gradient filling
915 //! @return true if processing was successful, or false otherwise
916 bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
918 Quantity_Color aColor1;
919 Quantity_Color aColor2;
920 if (!processGradientOption (aColor1, aColor2))
924 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
925 if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
929 theSetGradient (aColor1, aColor2, aGradientMode);
933 //! Processes the gradient mode option set
934 //! @return true if processing was successful, or false otherwise
935 bool processGradientModeOptionSet() const
937 return processGradientModeOptionSet (myGradientModeOptionKey);
940 //! Processes the gradient mode option set
941 //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
942 //! @return true if processing was successful, or false otherwise
943 bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
945 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
946 if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
950 setGradientMode (aGradientMode);
954 //! Processes the color option set
955 //! @param theSetColor the function used to set a background color
956 //! @return true if processing was successful, or false otherwise
957 bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
959 return processColorOptionSet (myColorOptionKey, theSetColor);
962 //! Processes the default color option set
963 //! @return true if processing was successful, or false otherwise
964 bool processDefaultGradientOptionSet() const
966 return processGradientOptionSet (setDefaultGradient);
969 //! Processes the default gradient option set
970 //! @return true if processing was successful, or false otherwise
971 bool processDefaultColorOptionSet() const
973 return processColorOptionSet (setDefaultColor);
976 //! Processes the color option set
977 //! @param theColorOptionKey the key of the option that is interpreted as a color option
978 //! @param theSetColor the function used to set a background color
979 //! @return true if processing was successful, or false otherwise
980 bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
981 SetColorFunction* const theSetColor = setColor) const
983 Quantity_Color aColor;
984 if (!processColorOption (theColorOptionKey, aColor))
988 theSetColor (aColor);
992 //! Processes the help option set
993 //! @param theBackgroundCommandName the name of the command that changes the background
994 //! @param theDrawInterpretor the interpreter of the Draw Harness application
995 //! @return true if processing was successful, or false otherwise
996 bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
998 const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
999 ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
1000 if (aNumberOfHelpOptionArguments != 0)
1004 return printHelp (theBackgroundCommandName, theDrawInterpretor);
1007 //! Processes the cubemap option
1008 //! @param theFilePaths the array of filenames of cubemap sides
1009 //! @return true if processing was successful, or false otherwise
1010 bool processCubeMapOptions (NCollection_Array1<TCollection_AsciiString> &theFilePaths) const
1012 const Standard_Integer aNumberOfCubeMapOptionArguments = myCommandParser.GetNumberOfOptionArguments (myCubeMapOptionKey);
1014 if (aNumberOfCubeMapOptionArguments != 1
1015 && aNumberOfCubeMapOptionArguments != 6)
1020 theFilePaths.Resize(0, aNumberOfCubeMapOptionArguments - 1, Standard_False);
1022 for (int i = 0; i < aNumberOfCubeMapOptionArguments; ++i)
1024 std::string aCubeMapFileName;
1025 if (!myCommandParser.Arg (myCubeMapOptionKey, i, aCubeMapFileName))
1029 theFilePaths[i] = aCubeMapFileName.c_str();
1035 //! Processes the inverted z cubemap option
1036 //! @return true if processing was successful, or false otherwise
1037 bool processCubeMapInvertedZOptionSet () const
1039 const Standard_Integer aNumberOfCubeMapZInversionOptionArguments =
1040 myCommandParser.GetNumberOfOptionArguments (myCubeMapInvertedZOptionKey);
1042 if (aNumberOfCubeMapZInversionOptionArguments != 0)
1050 //! Processes the option allowing to skip IBM maps generation
1051 //! @return true if processing was successful, or false otherwise
1052 bool processCubeMapDoNotGenPBREnvOptionSet() const
1054 const Standard_Integer aNumberOfCubeMapDoNotGenPBREnvOptionArguments =
1055 myCommandParser.GetNumberOfOptionArguments(myCubeMapDoNotGenPBREnvOptionKey);
1057 if (aNumberOfCubeMapDoNotGenPBREnvOptionArguments != 0)
1065 //! Processes the tiles order option
1066 //! @param theOrder the array of indexes if cubemap sides in tile grid
1067 //! @return true if processing was successful, or false otherwise
1068 bool processCubeMapOrderOptions (Graphic3d_CubeMapOrder& theOrder) const
1070 const Standard_Integer aNumberOfCubeMapOrderOptionArguments = myCommandParser.GetNumberOfOptionArguments(
1071 myCubeMapOrderOptionKey);
1073 if (aNumberOfCubeMapOrderOptionArguments != 6)
1079 for (unsigned int i = 0; i < 6; ++i)
1081 std::string anOrderItem;
1082 if (!myCommandParser.Arg (myCubeMapOrderOptionKey, i, anOrderItem))
1087 theOrder.Set (Graphic3d_CubeMapSide (i),
1088 static_cast<unsigned char> (Draw::Atoi (anOrderItem.c_str())));
1091 return theOrder.IsValid();
1094 //! Processes the image option
1095 //! @param theImageFileName the filename of the image to be used as a background
1096 //! @return true if processing was successful, or false otherwise
1097 bool processImageOption (std::string& theImageFileName) const
1099 const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1101 if (aNumberOfImageOptionArguments != 1)
1105 std::string anImageFileName;
1106 if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1110 theImageFileName = anImageFileName;
1114 //! Processes the image mode option
1115 //! @param theImageMode the fill type used for a background image
1116 //! @return true if processing was successful, or false otherwise
1117 bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1119 return processImageModeOption (myImageModeOptionKey, theImageMode);
1122 //! Processes the image mode option
1123 //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1124 //! @param theImageMode the fill type used for a background image
1125 //! @return true if processing was successful, or false otherwise
1126 bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1127 Aspect_FillMethod& theImageMode) const
1129 return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1132 //! Processes the gradient option
1133 //! @param theColor1 the gradient starting color
1134 //! @param theColor2 the gradient ending color
1135 //! @return true if processing was successful, or false otherwise
1136 bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1138 Standard_Integer anArgumentIndex = 0;
1139 Quantity_Color aColor1;
1140 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1144 Quantity_Color aColor2;
1145 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1149 const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1150 myGradientOptionKey);
1151 if (anArgumentIndex != aNumberOfGradientOptionArguments)
1155 theColor1 = aColor1;
1156 theColor2 = aColor2;
1160 //! Processes the gradient mode option
1161 //! @param theGradientMode the fill method used for a background gradient filling
1162 //! @return true if processing was successful, or false otherwise
1163 bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1165 return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1168 //! Processes the gradient mode option
1169 //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1170 //! @param theGradientMode the fill method used for a background gradient filling
1171 //! @return true if processing was successful, or false otherwise
1172 bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1173 Aspect_GradientFillMethod& theGradientMode) const
1175 return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1178 //! Processes some mode option
1179 //! @tparam TheMode the type of a mode to be processed
1180 //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1181 //! @param theMode a mode to be processed
1182 //! @return true if processing was successful, or false otherwise
1183 template <typename TheMode>
1184 bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1185 bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1186 TheMode& /* theMode */),
1187 TheMode& theMode) const
1189 const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1191 if (aNumberOfModeOptionArguments != 1)
1195 std::string aModeString;
1196 if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1200 TheMode aMode = TheMode();
1201 if (!theGetModeByName (aModeString.c_str(), aMode))
1209 //! Processes the color option
1210 //! @param theColor a color used for filling a background
1211 //! @return true if processing was successful, or false otherwise
1212 bool processColorOption (Quantity_Color& theColor) const
1214 return processColorOption (myColorOptionKey, theColor);
1217 //! Processes the color option
1218 //! @param theColorOptionKey the key of the option that is interpreted as a color option
1219 //! @param theColor a color used for filling a background
1220 //! @return true if processing was successful, or false otherwise
1221 bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1223 Standard_Integer anArgumentIndex = 0;
1224 Quantity_Color aColor;
1225 if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1229 const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1231 if (anArgumentIndex != aNumberOfColorOptionArguments)
1239 //! Prints helping message
1240 //! @param theBackgroundCommandName the name of the command that changes the background
1241 //! @param theDrawInterpretor the interpreter of the Draw Harness application
1242 //! @return true if printing was successful, or false otherwise
1243 static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1245 return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1248 //! Sets the cubemap as a background
1249 //! @param theFileNames the array of filenames of packed or multifile cubemap
1250 //! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
1251 static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
1252 const Graphic3d_ValidatedCubeMapOrder theOrder = Graphic3d_CubeMapOrder::Default(),
1253 bool theZIsInverted = false,
1254 bool theToGenPBREnv = true)
1256 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
1257 Handle(Graphic3d_CubeMap) aCubeMap;
1259 if (theFileNames.Size() == 1)
1260 aCubeMap = new Graphic3d_CubeMapPacked(theFileNames[0], theOrder);
1262 aCubeMap = new Graphic3d_CubeMapSeparate(theFileNames);
1264 aCubeMap->SetZInversion (theZIsInverted);
1266 aCubeMap->GetParams()->SetFilter(Graphic3d_TOTF_BILINEAR);
1267 aCubeMap->GetParams()->SetRepeat(Standard_False);
1268 aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
1270 aCurrentView->SetBackgroundCubeMap (aCubeMap, theToGenPBREnv, Standard_True);
1273 //! Sets the image as a background
1274 //! @param theImageFileName the filename of the image to be used as a background
1275 //! @param theImageMode the fill type used for a background image
1276 static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1278 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1279 aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1282 //! Sets the fill type used for a background image
1283 //! @param theImageMode the fill type used for a background image
1284 static void setImageMode (const Aspect_FillMethod theImageMode)
1286 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1287 aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1290 //! Sets the gradient filling for a background
1291 //! @param theColor1 the gradient starting color
1292 //! @param theColor2 the gradient ending color
1293 //! @param theGradientMode the fill method used for a background gradient filling
1294 static void setGradient (const Quantity_Color& theColor1,
1295 const Quantity_Color& theColor2,
1296 const Aspect_GradientFillMethod theGradientMode)
1298 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1299 aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1302 //! Sets the fill method used for a background gradient filling
1303 //! @param theGradientMode the fill method used for a background gradient filling
1304 static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1306 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1307 aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1310 //! Sets the color used for filling a background
1311 //! @param theColor the color used for filling a background
1312 static void setColor (const Quantity_Color& theColor)
1314 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1315 aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1316 aCurrentView->SetBackgroundColor (theColor);
1317 aCurrentView->Update();
1320 //! Sets the gradient filling for a background in a default viewer
1321 //! @param theColor1 the gradient starting color
1322 //! @param theColor2 the gradient ending color
1323 //! @param theGradientMode the fill method used for a background gradient filling
1324 static void setDefaultGradient (const Quantity_Color& theColor1,
1325 const Quantity_Color& theColor2,
1326 const Aspect_GradientFillMethod theGradientMode)
1328 ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1329 ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1330 ViewerTest_DefaultBackground.FillMethod = theGradientMode;
1331 setDefaultGradient();
1334 //! Sets the color used for filling a background in a default viewer
1335 //! @param theColor the color used for filling a background
1336 static void setDefaultColor (const Quantity_Color& theColor)
1338 ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1339 ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1340 ViewerTest_DefaultBackground.FillMethod = Aspect_GFM_NONE;
1341 ViewerTest_DefaultBackground.FlatColor = theColor;
1342 setDefaultGradient();
1346 //! Sets the gradient filling for a background in a default viewer.
1347 //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1348 static void setDefaultGradient()
1350 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1351 anInteractiveContextIterator (ViewerTest_myContexts);
1352 anInteractiveContextIterator.More();
1353 anInteractiveContextIterator.Next())
1355 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1356 aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1357 ViewerTest_DefaultBackground.GradientColor2,
1358 ViewerTest_DefaultBackground.FillMethod);
1362 //! Sets the color used for filling a background in a default viewer.
1363 //! The color value is taken from ViewerTest_DefaultBackground structure
1364 static void setDefaultColor()
1366 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1367 anInteractiveContextIterator (ViewerTest_myContexts);
1368 anInteractiveContextIterator.More();
1369 anInteractiveContextIterator.Next())
1371 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1372 aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1379 //==============================================================================
1382 static LRESULT WINAPI ViewerWindowProc(
1387 static LRESULT WINAPI AdvViewerWindowProc(
1395 //==============================================================================
1398 //==============================================================================
1400 const Handle(Standard_Transient)& ViewerTest::WClass()
1402 static Handle(Standard_Transient) theWClass;
1404 if (theWClass.IsNull())
1406 theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
1407 CS_VREDRAW | CS_HREDRAW, 0, 0,
1408 ::LoadCursor (NULL, IDC_ARROW));
1414 //==============================================================================
1415 //function : CreateName
1416 //purpose : Create numerical name for new object in theMap
1417 //==============================================================================
1418 template <typename ObjectType>
1419 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1420 const TCollection_AsciiString& theDefaultString)
1422 if (theObjectMap.IsEmpty())
1423 return theDefaultString + TCollection_AsciiString(1);
1425 Standard_Integer aNextKey = 1;
1426 Standard_Boolean isFound = Standard_False;
1429 TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1430 // Look for objects with default names
1431 if (theObjectMap.IsBound1(aStringKey))
1436 isFound = Standard_True;
1439 return theDefaultString + TCollection_AsciiString(aNextKey);
1442 //==============================================================================
1443 //structure : ViewerTest_Names
1444 //purpose : Allow to operate with full view name: driverName/viewerName/viewName
1445 //==============================================================================
1446 struct ViewerTest_Names
1449 TCollection_AsciiString myDriverName;
1450 TCollection_AsciiString myViewerName;
1451 TCollection_AsciiString myViewName;
1455 const TCollection_AsciiString& GetDriverName () const
1457 return myDriverName;
1459 void SetDriverName (const TCollection_AsciiString& theDriverName)
1461 myDriverName = theDriverName;
1463 const TCollection_AsciiString& GetViewerName () const
1465 return myViewerName;
1467 void SetViewerName (const TCollection_AsciiString& theViewerName)
1469 myViewerName = theViewerName;
1471 const TCollection_AsciiString& GetViewName () const
1475 void SetViewName (const TCollection_AsciiString& theViewName)
1477 myViewName = theViewName;
1480 //===========================================================================
1481 //function : Constructor for ViewerTest_Names
1482 //purpose : Get view, viewer, driver names from custom string
1483 //===========================================================================
1485 ViewerTest_Names (const TCollection_AsciiString& theInputString)
1487 TCollection_AsciiString aName(theInputString);
1488 if (theInputString.IsEmpty())
1490 // Get current configuration
1491 if (ViewerTest_myDrivers.IsEmpty())
1492 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1493 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1495 myDriverName = ViewerTest_myDrivers.Find2
1496 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1498 if(ViewerTest_myContexts.IsEmpty())
1500 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1501 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1505 myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
1508 myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
1512 // There is at least view name
1513 Standard_Integer aParserNumber = 0;
1514 for (Standard_Integer i = 0; i < 3; ++i)
1516 Standard_Integer aParserPos = aName.SearchFromEnd("/");
1517 if(aParserPos != -1)
1520 aName.Split(aParserPos-1);
1525 if (aParserNumber == 0)
1528 if (!ViewerTest::GetAISContext().IsNull())
1530 myDriverName = ViewerTest_myDrivers.Find2
1531 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1532 myViewerName = ViewerTest_myContexts.Find2
1533 (ViewerTest::GetAISContext());
1537 // There is no opened contexts here, need to create names for viewer and driver
1538 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1539 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1541 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1542 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1544 myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1546 else if (aParserNumber == 1)
1548 // Here is viewerName/viewName
1549 if (!ViewerTest::GetAISContext().IsNull())
1550 myDriverName = ViewerTest_myDrivers.Find2
1551 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1554 // There is no opened contexts here, need to create name for driver
1555 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1556 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1558 myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1560 myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1564 //Here is driverName/viewerName/viewName
1565 myDriverName = TCollection_AsciiString(aName);
1567 TCollection_AsciiString aViewerName(theInputString);
1568 aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1569 myViewerName = TCollection_AsciiString(aViewerName);
1571 myViewName = TCollection_AsciiString(theInputString);
1577 //==============================================================================
1578 //function : FindContextByView
1579 //purpose : Find AIS_InteractiveContext by View
1580 //==============================================================================
1582 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1584 Handle(AIS_InteractiveContext) anAISContext;
1586 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1587 anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1589 if (anIter.Value()->CurrentViewer() == theView->Viewer())
1590 return anIter.Key2();
1592 return anAISContext;
1595 //==============================================================================
1596 //function : IsWindowOverlapped
1597 //purpose : Check if theWindow overlapp another view
1598 //==============================================================================
1600 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1601 const Standard_Integer thePxTop,
1602 const Standard_Integer thePxRight,
1603 const Standard_Integer thePxBottom,
1604 TCollection_AsciiString& theViewId)
1606 for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1607 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1609 Standard_Integer aTop = 0,
1613 anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1614 if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1615 (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1616 (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1617 (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1619 theViewId = anIter.Key1();
1620 return Standard_True;
1623 return Standard_False;
1626 // Workaround: to create and delete non-orthographic views outside ViewerTest
1627 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1629 ViewerTest_myViews.UnBind1 (theName);
1632 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1633 const Handle(V3d_View)& theView)
1635 ViewerTest_myViews.Bind (theName, theView);
1638 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1640 return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1643 //! Auxiliary tool performing continuous redraws of specified window.
1644 class ViewerTest_ContinuousRedrawer
1647 //! Return global instance.
1648 static ViewerTest_ContinuousRedrawer& Instance()
1650 static ViewerTest_ContinuousRedrawer aRedrawer;
1656 ~ViewerTest_ContinuousRedrawer()
1662 void Start (const Handle(Aspect_Window)& theWindow,
1663 Standard_Real theTargetFps)
1665 if (myWindow != theWindow
1666 || myTargetFps != theTargetFps)
1669 myWindow = theWindow;
1670 myTargetFps = theTargetFps;
1672 if (myThread.GetId() == 0)
1675 myThread.Run (this);
1680 void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1682 if (!theWindow.IsNull()
1683 && myWindow != theWindow)
1689 Standard_Mutex::Sentry aLock (myMutex);
1702 Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1705 Standard_Real aTimeOld = 0.0;
1706 const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1710 Standard_Mutex::Sentry aLock (myMutex);
1716 if (myTargetFps > 0.0)
1718 const Standard_Real aTimeNew = aTimer.ElapsedTime();
1719 const Standard_Real aDuration = aTimeNew - aTimeOld;
1720 if (aDuration >= aTargetDur)
1722 myWindow->InvalidateContent (aDisp);
1723 aTimeOld = aTimeNew;
1728 myWindow->InvalidateContent (aDisp);
1731 OSD::MilliSecSleep (1);
1735 //! Thread creation callback.
1736 static Standard_Address doThreadWrapper (Standard_Address theData)
1738 ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1739 aThis->doThreadLoop();
1743 //! Empty constructor.
1744 ViewerTest_ContinuousRedrawer()
1745 : myThread (doThreadWrapper),
1750 Handle(Aspect_Window) myWindow;
1751 OSD_Thread myThread;
1752 Standard_Mutex myMutex;
1753 Standard_Real myTargetFps;
1754 volatile bool myToStop;
1757 //==============================================================================
1758 //function : ViewerInit
1759 //purpose : Create the window viewer and initialize all the global variable
1760 //==============================================================================
1762 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1763 const Standard_Integer thePxTop,
1764 const Standard_Integer thePxWidth,
1765 const Standard_Integer thePxHeight,
1766 const TCollection_AsciiString& theViewName,
1767 const TCollection_AsciiString& theDisplayName,
1768 const Handle(V3d_View)& theViewToClone)
1770 // Default position and dimension of the viewer window.
1771 // Note that left top corner is set to be sufficiently small to have
1772 // window fit in the small screens (actual for remote desktops, see #23003).
1773 // The position corresponds to the window's client area, thus some
1774 // gap is added for window frame to be visible.
1775 Standard_Integer aPxLeft = 20;
1776 Standard_Integer aPxTop = 40;
1777 Standard_Integer aPxWidth = 409;
1778 Standard_Integer aPxHeight = 409;
1779 Standard_Boolean toCreateViewer = Standard_False;
1780 if (!theViewToClone.IsNull())
1782 theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1785 Handle(OpenGl_GraphicDriver) aGraphicDriver;
1786 ViewerTest_Names aViewNames(theViewName);
1787 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1788 aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1791 aPxLeft = thePxLeft;
1794 if (thePxWidth != 0)
1795 aPxWidth = thePxWidth;
1796 if (thePxHeight != 0)
1797 aPxHeight = thePxHeight;
1799 // Get graphic driver (create it or get from another view)
1800 const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1803 // Get connection string
1804 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1805 if (!theDisplayName.IsEmpty())
1807 SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1811 ::Display* aDispX = NULL;
1812 // create dedicated display connection instead of reusing Tk connection
1813 // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1814 /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1815 Tcl_Interp* aTclInterp = aCommands.Interp();
1816 Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1817 aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1818 SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1821 (void)theDisplayName; // avoid warning on unused argument
1822 SetDisplayConnection (new Aspect_DisplayConnection ());
1825 if (Draw_VirtualWindows)
1827 // don't waste the time waiting for VSync when window is not displayed on the screen
1828 ViewerTest_myDefaultCaps.swapInterval = 0;
1829 // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1830 //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1832 aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
1833 aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
1834 aGraphicDriver->InitContext();
1836 ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1837 toCreateViewer = Standard_True;
1841 aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
1844 //Dispose the window if input parameters are default
1845 if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
1847 Standard_Integer aTop = 0,
1854 // Get screen resolution
1855 #if defined(_WIN32) || defined(__WIN32__)
1857 GetClientRect(GetDesktopWindow(), &aWindowSize);
1858 aScreenHeight = aWindowSize.bottom;
1859 aScreenWidth = aWindowSize.right;
1860 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1861 GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1863 Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1864 aScreenWidth = WidthOfScreen(aScreen);
1865 aScreenHeight = HeightOfScreen(aScreen);
1868 TCollection_AsciiString anOverlappedViewId("");
1870 while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
1872 ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1874 if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1875 && aRight + 2*aPxWidth + 40 > aScreenWidth)
1877 if (aBottom + aPxHeight + 40 > aScreenHeight)
1884 aPxTop = aBottom + 40;
1887 aPxLeft = aRight + 20;
1892 TCollection_AsciiString aTitle("3D View - ");
1893 aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1895 // Change name of current active window
1896 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
1898 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
1902 Handle(V3d_Viewer) a3DViewer;
1903 // If it's the single view, we first look for empty context
1904 if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1906 NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1907 anIter(ViewerTest_myContexts);
1909 ViewerTest::SetAISContext (anIter.Value());
1910 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1912 else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1914 ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1915 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
1917 else if (a3DViewer.IsNull())
1919 toCreateViewer = Standard_True;
1920 a3DViewer = new V3d_Viewer(aGraphicDriver);
1921 a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1922 a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1923 ViewerTest_DefaultBackground.GradientColor2,
1924 ViewerTest_DefaultBackground.FillMethod);
1927 // AIS context setup
1928 if (ViewerTest::GetAISContext().IsNull() ||
1929 !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1931 Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
1932 ViewerTest::SetAISContext (aContext);
1933 ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1937 ViewerTest::ResetEventManager();
1942 VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1943 Handle(WNT_WClass)::DownCast (WClass()),
1944 Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
1946 aPxWidth, aPxHeight,
1947 Quantity_NOC_BLACK);
1948 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1949 VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1951 aPxWidth, aPxHeight);
1952 ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
1954 VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1957 aPxWidth, aPxHeight);
1959 VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
1962 Handle(V3d_View) aView;
1963 if (!theViewToClone.IsNull())
1965 aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
1969 aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
1972 aView->SetWindow (VT_GetWindow());
1973 ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
1975 ViewerTest::CurrentView(aView);
1976 ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
1978 // Setup for X11 or NT
1981 // Set parameters for V3d_View and V3d_Viewer
1982 const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1983 aV3dView->SetComputedMode(Standard_False);
1985 a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1988 a3DViewer->SetDefaultLights();
1989 a3DViewer->SetLightOn();
1992 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1995 ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1996 Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
2000 VT_GetWindow()->Map();
2002 // Set the handle of created view in the event manager
2003 ViewerTest::ResetEventManager();
2005 ViewerTest::CurrentView()->Redraw();
2008 a3DViewer.Nullify();
2010 return aViewNames.GetViewName();
2013 //==============================================================================
2014 //function : RedrawAllViews
2015 //purpose : Redraw all created views
2016 //==============================================================================
2017 void ViewerTest::RedrawAllViews()
2019 NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2020 for (; aViewIt.More(); aViewIt.Next())
2022 const Handle(V3d_View)& aView = aViewIt.Key2();
2027 //==============================================================================
2029 //purpose : Create the window viewer and initialize all the global variable
2030 // Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
2031 //==============================================================================
2033 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2035 TCollection_AsciiString aViewName, aDisplayName;
2036 Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
2037 Handle(V3d_View) aCopyFrom;
2038 TCollection_AsciiString aName, aValue;
2040 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
2042 const TCollection_AsciiString anArg = theArgVec[anArgIt];
2043 TCollection_AsciiString anArgCase = anArg;
2044 anArgCase.LowerCase();
2045 if (anArgIt + 1 < theArgsNb
2046 && anArgCase == "-name")
2048 aViewName = theArgVec[++anArgIt];
2050 else if (anArgIt + 1 < theArgsNb
2051 && (anArgCase == "-left"
2052 || anArgCase == "-l"))
2054 aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2056 else if (anArgIt + 1 < theArgsNb
2057 && (anArgCase == "-top"
2058 || anArgCase == "-t"))
2060 aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2062 else if (anArgIt + 1 < theArgsNb
2063 && (anArgCase == "-width"
2064 || anArgCase == "-w"))
2066 aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2068 else if (anArgIt + 1 < theArgsNb
2069 && (anArgCase == "-height"
2070 || anArgCase == "-h"))
2072 aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2074 else if (anArgCase == "-exitonclose")
2076 ViewerTest_EventManager::ToExitOnCloseView() = true;
2077 if (anArgIt + 1 < theArgsNb
2078 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
2083 else if (anArgCase == "-closeonescape"
2084 || anArgCase == "-closeonesc")
2086 ViewerTest_EventManager::ToCloseViewOnEscape() = true;
2087 if (anArgIt + 1 < theArgsNb
2088 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
2093 else if (anArgCase == "-2d_mode"
2094 || anArgCase == "-2dmode"
2095 || anArgCase == "-2d")
2097 bool toEnable = true;
2098 if (anArgIt + 1 < theArgsNb
2099 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2103 is2dMode = toEnable ? 1 : 0;
2105 else if (anArgIt + 1 < theArgsNb
2106 && (anArgCase == "-disp"
2107 || anArgCase == "-display"))
2109 aDisplayName = theArgVec[++anArgIt];
2111 else if (!ViewerTest::CurrentView().IsNull()
2112 && aCopyFrom.IsNull()
2113 && (anArgCase == "-copy"
2114 || anArgCase == "-clone"
2115 || anArgCase == "-cloneactive"
2116 || anArgCase == "-cloneactiveview"))
2118 aCopyFrom = ViewerTest::CurrentView();
2121 else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2124 if (aName == "name")
2128 else if (aName == "l"
2131 aPxLeft = aValue.IntegerValue();
2133 else if (aName == "t"
2136 aPxTop = aValue.IntegerValue();
2138 else if (aName == "disp"
2139 || aName == "display")
2141 aDisplayName = aValue;
2143 else if (aName == "w"
2144 || aName == "width")
2146 aPxWidth = aValue.IntegerValue();
2148 else if (aName == "h"
2149 || aName == "height")
2151 aPxHeight = aValue.IntegerValue();
2155 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2159 else if (aViewName.IsEmpty())
2165 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2170 #if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2171 if (!aDisplayName.IsEmpty())
2173 aDisplayName.Clear();
2174 std::cout << "Warning: display parameter will be ignored.\n";
2178 ViewerTest_Names aViewNames (aViewName);
2179 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
2181 TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2182 theDi.Eval (aCommand.ToCString());
2185 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2190 TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
2191 aViewName, aDisplayName, aCopyFrom);
2194 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2200 //! Parse HLR algo type.
2201 static Standard_Boolean parseHlrAlgoType (const char* theName,
2202 Prs3d_TypeOfHLR& theType)
2204 TCollection_AsciiString aName (theName);
2206 if (aName == "polyalgo")
2208 theType = Prs3d_TOH_PolyAlgo;
2210 else if (aName == "algo")
2212 theType = Prs3d_TOH_Algo;
2216 return Standard_False;
2218 return Standard_True;
2221 //==============================================================================
2223 //purpose : hidden lines removal algorithm
2224 //==============================================================================
2226 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2228 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2229 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2232 std::cerr << "Error: No opened viewer!\n";
2236 Standard_Boolean hasHlrOnArg = Standard_False;
2237 Standard_Boolean hasShowHiddenArg = Standard_False;
2238 Standard_Boolean isHLROn = Standard_False;
2239 Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2240 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2241 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2242 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2244 TCollection_AsciiString anArg (argv[anArgIter]);
2246 if (anUpdateTool.parseRedrawMode (anArg))
2250 else if (anArg == "-showhidden"
2251 && anArgIter + 1 < argc
2252 && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2255 hasShowHiddenArg = Standard_True;
2258 else if ((anArg == "-type"
2260 || anArg == "-algotype")
2261 && anArgIter + 1 < argc
2262 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2267 else if (!hasHlrOnArg
2268 && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2270 hasHlrOnArg = Standard_True;
2274 else if (!hasShowHiddenArg
2275 && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2277 hasShowHiddenArg = Standard_True;
2282 std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2288 di << "HLR: " << aView->ComputedMode() << "\n";
2289 di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2291 switch (aCtx->DefaultDrawer()->TypeOfHLR())
2293 case Prs3d_TOH_NotSet: di << "NotSet\n"; break;
2294 case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2295 case Prs3d_TOH_Algo: di << "Algo\n"; break;
2297 anUpdateTool.Invalidate();
2301 Standard_Boolean toRecompute = Standard_False;
2302 if (aTypeOfHLR != Prs3d_TOH_NotSet
2303 && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
2305 toRecompute = Standard_True;
2306 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2308 if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2310 toRecompute = Standard_True;
2313 aCtx->DefaultDrawer()->EnableDrawHiddenLine();
2317 aCtx->DefaultDrawer()->DisableDrawHiddenLine();
2322 if (aView->ComputedMode() && isHLROn && toRecompute)
2324 AIS_ListOfInteractive aListOfShapes;
2325 aCtx->DisplayedObjects (aListOfShapes);
2326 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
2328 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
2330 aCtx->Redisplay (aShape, Standard_False);
2335 aView->SetComputedMode (isHLROn);
2339 //==============================================================================
2340 //function : VHLRType
2341 //purpose : change type of using HLR algorithm
2342 //==============================================================================
2344 static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
2346 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2347 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2350 std::cerr << "Error: No opened viewer!\n";
2354 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2355 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2356 AIS_ListOfInteractive aListOfShapes;
2357 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
2359 TCollection_AsciiString anArg (argv[anArgIter]);
2361 if (anUpdateTool.parseRedrawMode (anArg))
2365 else if ((anArg == "-type"
2367 || anArg == "-algotype")
2368 && anArgIter + 1 < argc
2369 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2375 else if (aTypeOfHLR == Prs3d_TOH_NotSet
2376 && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2382 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
2383 TCollection_AsciiString aName (argv[anArgIter]);
2384 if (!aMap.IsBound2 (aName))
2386 std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2390 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2391 if (aShape.IsNull())
2393 std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2396 aListOfShapes.Append (aShape);
2400 if (aTypeOfHLR == Prs3d_TOH_NotSet)
2402 std::cout << "Syntax error: wrong number of arguments!\n";
2406 const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2409 aCtx->DisplayedObjects (aListOfShapes);
2410 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2413 for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2415 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2416 if (aShape.IsNull())
2421 const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2422 && aView->ComputedMode();
2424 || aShape->TypeOfHLR() != aTypeOfHLR)
2426 aShape->SetTypeOfHLR (aTypeOfHLR);
2430 aCtx->Redisplay (aShape, Standard_False);
2436 //==============================================================================
2437 //function : FindViewIdByWindowHandle
2438 //purpose : Find theView Id in the map of views by window handle
2439 //==============================================================================
2440 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2441 TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
2443 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2444 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2446 Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
2447 if (aWindowHandle == theWindowHandle)
2448 return anIter.Key1();
2450 return TCollection_AsciiString("");
2454 //! Make the view active
2455 void ActivateView (const TCollection_AsciiString& theViewName,
2456 Standard_Boolean theToUpdate = Standard_True)
2458 const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2464 Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2465 if (!anAISContext.IsNull())
2467 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
2469 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
2472 ViewerTest::CurrentView (aView);
2473 ViewerTest::SetAISContext (anAISContext);
2474 aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
2476 VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
2477 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
2478 VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
2480 VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
2482 SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2485 ViewerTest::CurrentView()->Redraw();
2490 //==============================================================================
2491 //function : RemoveView
2493 //==============================================================================
2494 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2495 const Standard_Boolean theToRemoveContext)
2497 if (!ViewerTest_myViews.IsBound2 (theView))
2502 const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2503 RemoveView (aViewName, theToRemoveContext);
2506 //==============================================================================
2507 //function : RemoveView
2508 //purpose : Close and remove view from display, clear maps if neccessary
2509 //==============================================================================
2510 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2512 if (!ViewerTest_myViews.IsBound1(theViewName))
2514 std::cout << "Wrong view name\n";
2518 // Activate another view if it's active now
2519 if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2521 if (ViewerTest_myViews.Extent() > 1)
2523 TCollection_AsciiString aNewViewName;
2524 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2525 anIter.More(); anIter.Next())
2527 if (anIter.Key1() != theViewName)
2529 aNewViewName = anIter.Key1();
2533 ActivateView (aNewViewName);
2537 VT_GetWindow().Nullify();
2538 ViewerTest::CurrentView (Handle(V3d_View)());
2539 if (isContextRemoved)
2541 Handle(AIS_InteractiveContext) anEmptyContext;
2542 ViewerTest::SetAISContext(anEmptyContext);
2548 Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2549 Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
2550 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2551 aRedrawer.Stop (aView->Window());
2553 // Remove view resources
2554 ViewerTest_myViews.UnBind1(theViewName);
2555 aView->Window()->Unmap();
2558 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2559 XFlush (GetDisplayConnection()->GetDisplay());
2562 // Keep context opened only if the closed view is last to avoid
2563 // unused empty contexts
2564 if (!aCurrentContext.IsNull())
2566 // Check if there are more difined views in the viewer
2567 aCurrentContext->CurrentViewer()->InitDefinedViews();
2568 if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2570 // Remove driver if there is no viewers that use it
2571 Standard_Boolean isRemoveDriver = Standard_True;
2572 for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2573 anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2575 if (aCurrentContext != anIter.Key2() &&
2576 aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2578 isRemoveDriver = Standard_False;
2583 aCurrentContext->RemoveAll (Standard_False);
2586 ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2587 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2588 Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
2592 ViewerTest_myContexts.UnBind2(aCurrentContext);
2595 std::cout << "3D View - " << theViewName << " was deleted.\n";
2596 if (ViewerTest_EventManager::ToExitOnCloseView())
2598 Draw_Interprete ("exit");
2602 //==============================================================================
2604 //purpose : Remove the view defined by its name
2605 //==============================================================================
2607 static int VClose (Draw_Interpretor& /*theDi*/,
2608 Standard_Integer theArgsNb,
2609 const char** theArgVec)
2611 NCollection_List<TCollection_AsciiString> aViewList;
2614 TCollection_AsciiString anArg (theArgVec[1]);
2616 if (anArg.IsEqual ("ALL")
2617 || anArg.IsEqual ("*"))
2619 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2620 anIter.More(); anIter.Next())
2622 aViewList.Append (anIter.Key1());
2624 if (aViewList.IsEmpty())
2626 std::cout << "No view to close\n";
2632 ViewerTest_Names aViewName (theArgVec[1]);
2633 if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2635 std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2638 aViewList.Append (aViewName.GetViewName());
2643 // close active view
2644 if (ViewerTest::CurrentView().IsNull())
2646 std::cerr << "No active view!\n";
2649 aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2652 Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
2653 for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2654 anIter.More(); anIter.Next())
2656 ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
2662 //==============================================================================
2663 //function : VActivate
2664 //purpose : Activate the view defined by its ID
2665 //==============================================================================
2667 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2671 theDi.Eval("vviewlist");
2675 TCollection_AsciiString aNameString;
2676 Standard_Boolean toUpdate = Standard_True;
2677 Standard_Boolean toActivate = Standard_True;
2678 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
2680 TCollection_AsciiString anArg (theArgVec[anArgIter]);
2683 && anArg == "-noupdate")
2685 toUpdate = Standard_False;
2688 && aNameString.IsEmpty()
2691 ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
2692 VT_GetWindow().Nullify();
2693 ViewerTest::CurrentView (Handle(V3d_View)());
2694 ViewerTest::ResetEventManager();
2695 theDi << theArgVec[0] << ": all views are inactive\n";
2696 toActivate = Standard_False;
2699 && aNameString.IsEmpty())
2701 aNameString = theArgVec[anArgIter];
2705 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2714 else if (aNameString.IsEmpty())
2716 std::cout << "Syntax error: wrong number of arguments\n";
2720 // Check if this view exists in the viewer with the driver
2721 ViewerTest_Names aViewNames (aNameString);
2722 if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2724 theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
2728 // Check if it is active already
2729 if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2731 theDi << theArgVec[0] << ": the view is active already\n";
2735 ActivateView (aViewNames.GetViewName(), toUpdate);
2739 //==============================================================================
2740 //function : VViewList
2741 //purpose : Print current list of views per viewer and graphic driver ID
2742 // shared between viewers
2743 //==============================================================================
2745 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2749 theDi << theArgVec[0] << ": Wrong number of command arguments\n"
2750 << "Usage: " << theArgVec[0] << " name";
2753 if (ViewerTest_myContexts.Size() < 1)
2756 Standard_Boolean isTreeView =
2757 (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
2761 theDi << theArgVec[0] <<":\n";
2764 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2765 aDriverIter.More(); aDriverIter.Next())
2768 theDi << aDriverIter.Key1() << ":\n";
2770 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2771 aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2773 if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
2777 TCollection_AsciiString aContextName(aContextIter.Key1());
2778 theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2781 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2782 aViewIter.More(); aViewIter.Next())
2784 if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
2786 TCollection_AsciiString aViewName(aViewIter.Key1());
2789 if (aViewIter.Value() == ViewerTest::CurrentView())
2790 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
2792 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2796 theDi << aViewName << " ";
2806 //==============================================================================
2807 //function : GetMousePosition
2809 //==============================================================================
2810 void ViewerTest::GetMousePosition (Standard_Integer& theX,
2811 Standard_Integer& theY)
2813 if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
2815 theX = aViewCtrl->LastMousePosition().x();
2816 theY = aViewCtrl->LastMousePosition().y();
2820 //==============================================================================
2821 //function : VViewProj
2822 //purpose : Switch view projection
2823 //==============================================================================
2824 static int VViewProj (Draw_Interpretor& ,
2825 Standard_Integer theNbArgs,
2826 const char** theArgVec)
2828 static Standard_Boolean isYup = Standard_False;
2829 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2832 std::cout << "Error: no active view\n";
2836 TCollection_AsciiString aCmdName (theArgVec[0]);
2837 Standard_Boolean isGeneralCmd = Standard_False;
2838 if (aCmdName == "vfront")
2840 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2842 else if (aCmdName == "vback")
2844 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2846 else if (aCmdName == "vtop")
2848 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2850 else if (aCmdName == "vbottom")
2852 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2854 else if (aCmdName == "vleft")
2856 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2858 else if (aCmdName == "vright")
2860 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2862 else if (aCmdName == "vaxo")
2864 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2868 isGeneralCmd = Standard_True;
2869 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2871 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2872 anArgCase.LowerCase();
2873 if (anArgCase == "-zup")
2875 isYup = Standard_False;
2877 else if (anArgCase == "-yup")
2879 isYup = Standard_True;
2881 else if (anArgCase == "-front"
2882 || anArgCase == "front"
2883 || anArgCase == "-f"
2884 || anArgCase == "f")
2886 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2888 else if (anArgCase == "-back"
2889 || anArgCase == "back"
2890 || anArgCase == "-b"
2891 || anArgCase == "b")
2893 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2895 else if (anArgCase == "-top"
2896 || anArgCase == "top"
2897 || anArgCase == "-t"
2898 || anArgCase == "t")
2900 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2902 else if (anArgCase == "-bottom"
2903 || anArgCase == "bottom"
2904 || anArgCase == "-bot"
2905 || anArgCase == "bot"
2906 || anArgCase == "-b"
2907 || anArgCase == "b")
2909 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2911 else if (anArgCase == "-left"
2912 || anArgCase == "left"
2913 || anArgCase == "-l"
2914 || anArgCase == "l")
2916 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2918 else if (anArgCase == "-right"
2919 || anArgCase == "right"
2920 || anArgCase == "-r"
2921 || anArgCase == "r")
2923 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2925 else if (anArgCase == "-axoleft"
2926 || anArgCase == "-leftaxo"
2927 || anArgCase == "axoleft"
2928 || anArgCase == "leftaxo")
2930 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2932 else if (anArgCase == "-axo"
2933 || anArgCase == "axo"
2934 || anArgCase == "-a"
2936 || anArgCase == "-axoright"
2937 || anArgCase == "-rightaxo"
2938 || anArgCase == "axoright"
2939 || anArgCase == "rightaxo")
2941 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2943 else if (anArgCase == "+x")
2945 aView->SetProj (V3d_Xpos, isYup);
2947 else if (anArgCase == "-x")
2949 aView->SetProj (V3d_Xneg, isYup);
2951 else if (anArgCase == "+y")
2953 aView->SetProj (V3d_Ypos, isYup);
2955 else if (anArgCase == "-y")
2957 aView->SetProj (V3d_Yneg, isYup);
2959 else if (anArgCase == "+z")
2961 aView->SetProj (V3d_Zpos, isYup);
2963 else if (anArgCase == "-z")
2965 aView->SetProj (V3d_Zneg, isYup);
2967 else if (anArgCase == "+x+y+z")
2969 aView->SetProj (V3d_XposYposZpos, isYup);
2971 else if (anArgCase == "+x+y-z")
2973 aView->SetProj (V3d_XposYposZneg, isYup);
2975 else if (anArgCase == "+x-y+z")
2977 aView->SetProj (V3d_XposYnegZpos, isYup);
2979 else if (anArgCase == "+x-y-z")
2981 aView->SetProj (V3d_XposYnegZneg, isYup);
2983 else if (anArgCase == "-x+y+z")
2985 aView->SetProj (V3d_XnegYposZpos, isYup);
2987 else if (anArgCase == "-x+y-z")
2989 aView->SetProj (V3d_XnegYposZneg, isYup);
2991 else if (anArgCase == "-x-y+z")
2993 aView->SetProj (V3d_XnegYnegZpos, isYup);
2995 else if (anArgCase == "-x-y-z")
2997 aView->SetProj (V3d_XnegYnegZneg, isYup);
2999 else if (anArgCase == "+x+y")
3001 aView->SetProj (V3d_XposYpos, isYup);
3003 else if (anArgCase == "+x-y")
3005 aView->SetProj (V3d_XposYneg, isYup);
3007 else if (anArgCase == "-x+y")
3009 aView->SetProj (V3d_XnegYpos, isYup);
3011 else if (anArgCase == "-x-y")
3013 aView->SetProj (V3d_XnegYneg, isYup);
3015 else if (anArgCase == "+x+z")
3017 aView->SetProj (V3d_XposZpos, isYup);
3019 else if (anArgCase == "+x-z")
3021 aView->SetProj (V3d_XposZneg, isYup);
3023 else if (anArgCase == "-x+z")
3025 aView->SetProj (V3d_XnegZpos, isYup);
3027 else if (anArgCase == "-x-z")
3029 aView->SetProj (V3d_XnegZneg, isYup);
3031 else if (anArgCase == "+y+z")
3033 aView->SetProj (V3d_YposZpos, isYup);
3035 else if (anArgCase == "+y-z")
3037 aView->SetProj (V3d_YposZneg, isYup);
3039 else if (anArgCase == "-y+z")
3041 aView->SetProj (V3d_YnegZpos, isYup);
3043 else if (anArgCase == "-y-z")
3045 aView->SetProj (V3d_YnegZneg, isYup);
3047 else if (anArgIter + 1 < theNbArgs
3048 && anArgCase == "-frame"
3049 && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3051 TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3052 aFrameDef.LowerCase();
3053 gp_Dir aRight, anUp;
3054 if (aFrameDef.Value (2) == aFrameDef.Value (4))
3056 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3060 if (aFrameDef.Value (2) == 'x')
3062 aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3064 else if (aFrameDef.Value (2) == 'y')
3066 aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3068 else if (aFrameDef.Value (2) == 'z')
3070 aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3074 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3078 if (aFrameDef.Value (4) == 'x')
3080 anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3082 else if (aFrameDef.Value (4) == 'y')
3084 anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3086 else if (aFrameDef.Value (4) == 'z')
3088 anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3092 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3096 const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3097 const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3098 const gp_Dir aDir = anUp.Crossed (aRight);
3099 aCamera->SetCenter (gp_Pnt (0, 0, 0));
3100 aCamera->SetDirection (aDir);
3101 aCamera->SetUp (anUp);
3102 aCamera->OrthogonalizeUp();
3104 aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3109 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3118 std::cout << "Syntax error: wrong number of arguments\n";
3124 //==============================================================================
3126 //purpose : Dsiplay help on viewer Keyboead and mouse commands
3127 //Draw arg : No args
3128 //==============================================================================
3130 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3132 di << "=========================\n";
3133 di << "F : FitAll\n";
3134 di << "T : TopView\n";
3135 di << "B : BottomView\n";
3136 di << "R : RightView\n";
3137 di << "L : LeftView\n";
3138 di << "A : AxonometricView\n";
3139 di << "D : ResetView\n";
3141 di << "=========================\n";
3142 di << "S : Shading\n";
3143 di << "W : Wireframe\n";
3144 di << "H : HiddenLineRemoval\n";
3145 di << "U : Unset display mode\n";
3146 di << "Delete : Remove selection from viewer\n";
3148 di << "=========================\n";
3149 di << "Selection mode \n";
3150 di << "0 : Shape\n";
3151 di << "1 : Vertex\n";
3155 di << "5 : Shell\n";
3156 di << "6 : Solid\n";
3157 di << "7 : Compound\n";
3159 di << "=========================\n";
3160 di << "< : Hilight next detected\n";
3161 di << "> : Hilight previous detected\n";
3168 static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3173 if (ViewerTest_myViews.IsEmpty())
3175 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3182 // Delete view from map of views
3183 ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3188 if (LOWORD(wParam) == WA_CLICKACTIVE
3189 || LOWORD(wParam) == WA_ACTIVE
3190 || ViewerTest::CurrentView().IsNull())
3192 // Activate inactive window
3193 if (VT_GetWindow().IsNull()
3194 || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3196 ActivateView (FindViewIdByWindowHandle (theWinHandle));
3203 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3209 static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3214 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3217 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3225 BeginPaint(theWinHandle, &aPaint);
3226 EndPaint (theWinHandle, &aPaint);
3227 ViewerTest::CurrentEventManager()->ProcessExpose();
3232 ViewerTest::CurrentEventManager()->ProcessConfigure();
3239 switch (aView->RenderingParams().StereoMode)
3241 case Graphic3d_StereoMode_RowInterlaced:
3242 case Graphic3d_StereoMode_ColumnInterlaced:
3243 case Graphic3d_StereoMode_ChessBoard:
3245 // track window moves to reverse stereo pair
3246 aView->MustBeResized();
3258 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3259 if (aVKey != Aspect_VKey_UNKNOWN)
3261 const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3262 if (theMsg == WM_KEYDOWN)
3264 ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3268 ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3270 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3277 case WM_LBUTTONDOWN:
3278 case WM_MBUTTONDOWN:
3279 case WM_RBUTTONDOWN:
3281 const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3282 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3283 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3287 case WM_LBUTTONDOWN:
3288 aButton = Aspect_VKeyMouse_LeftButton;
3291 case WM_MBUTTONDOWN:
3292 aButton = Aspect_VKeyMouse_MiddleButton;
3295 case WM_RBUTTONDOWN:
3296 aButton = Aspect_VKeyMouse_RightButton;
3299 if (theMsg == WM_LBUTTONDOWN
3300 || theMsg == WM_MBUTTONDOWN
3301 || theMsg == WM_RBUTTONDOWN)
3303 if (aButton == Aspect_VKeyMouse_LeftButton)
3305 TheIsAnimating = Standard_False;
3308 SetFocus (theWinHandle);
3309 SetCapture(theWinHandle);
3310 ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3315 ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3317 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3322 const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3323 const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3324 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3325 Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3326 POINT aCursorPnt = { aPos.x(), aPos.y() };
3327 if (ScreenToClient (theWinHandle, &aCursorPnt))
3329 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3332 ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3333 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3338 Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3339 Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3340 Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(wParam);
3342 // don't make a slide-show from input events - fetch the actual mouse cursor position
3344 aCursor.cbSize = sizeof(aCursor);
3345 if (::GetCursorInfo (&aCursor) != FALSE)
3347 POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3348 if (ScreenToClient (theWinHandle, &aCursorPnt))
3350 // as we override mouse position, we need overriding also mouse state
3351 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3352 aButtons = WNT_Window::MouseButtonsAsync();
3353 aFlags = WNT_Window::MouseKeyFlagsAsync();
3357 if (VT_GetWindow().IsNull()
3358 || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
3360 // mouse move events come also for inactive windows
3364 ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3365 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), aView, true);
3370 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
3376 //==============================================================================
3377 //function : ViewerMainLoop
3378 //purpose : Get a Event on the view and dispatch it
3379 //==============================================================================
3381 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3383 Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager();
3384 if (aViewCtrl.IsNull()
3390 aViewCtrl->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3392 std::cout << "Start picking\n";
3396 while (aViewCtrl->ToPickPoint())
3398 // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
3399 if (GetMessageW (&aMsg, NULL, 0, 0))
3401 TranslateMessage (&aMsg);
3402 DispatchMessageW (&aMsg);
3406 std::cout << "Picking done\n";
3410 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
3412 int min( int a, int b )
3420 int max( int a, int b )
3428 int ViewerMainLoop (Standard_Integer theNbArgs, const char** theArgVec)
3430 static XEvent aReport;
3431 const Standard_Boolean toPick = theNbArgs > 0;
3434 if (ViewerTest::CurrentEventManager().IsNull())
3438 ViewerTest::CurrentEventManager()->StartPickPoint (theArgVec[1], theArgVec[2], theArgVec[3]);
3441 Display* aDisplay = GetDisplayConnection()->GetDisplay();
3442 XNextEvent (aDisplay, &aReport);
3444 // Handle event for the chosen display connection
3445 switch (aReport.type)
3449 if ((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
3452 ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
3453 return toPick ? 0 : 1;
3459 // Activate inactive view
3460 Window aWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3461 if (aWindow != aReport.xfocus.window)
3463 ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
3469 Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3470 if (anXWindow == aReport.xexpose.window)
3472 ViewerTest::CurrentEventManager()->ProcessExpose();
3475 // remove all the ExposureMask and process them at once
3476 for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3478 if (!XCheckWindowEvent (aDisplay, anXWindow, ExposureMask, &aReport))
3486 case ConfigureNotify:
3488 // remove all the StructureNotifyMask and process them at once
3489 Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3490 for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3492 if (!XCheckWindowEvent (aDisplay, anXWindow, StructureNotifyMask, &aReport))
3498 if (anXWindow == aReport.xconfigure.window)
3500 ViewerTest::CurrentEventManager()->ProcessConfigure();
3507 XKeyEvent* aKeyEvent = (XKeyEvent* )&aReport;
3508 const KeySym aKeySym = XLookupKeysym (aKeyEvent, 0);
3509 const Aspect_VKey aVKey = Xw_Window::VirtualKeyFromNative (aKeySym);
3510 if (aVKey != Aspect_VKey_UNKNOWN)
3512 const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3513 if (aReport.type == KeyPress)
3515 ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
3519 ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
3521 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3528 const Graphic3d_Vec2i aPos (aReport.xbutton.x, aReport.xbutton.y);
3529 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3530 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3531 if (aReport.xbutton.button == Button1)
3533 aButton = Aspect_VKeyMouse_LeftButton;
3535 if (aReport.xbutton.button == Button2)
3537 aButton = Aspect_VKeyMouse_MiddleButton;
3539 if (aReport.xbutton.button == Button3)
3541 aButton = Aspect_VKeyMouse_RightButton;
3544 if (aReport.xbutton.state & ControlMask)
3546 aFlags |= Aspect_VKeyFlags_CTRL;
3548 if (aReport.xbutton.state & ShiftMask)
3550 aFlags |= Aspect_VKeyFlags_SHIFT;
3552 if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3554 aFlags |= Aspect_VKeyFlags_ALT;
3557 if (aReport.xbutton.button == Button4
3558 || aReport.xbutton.button == Button5)
3560 if (aReport.type != ButtonPress)
3565 const double aDeltaF = (aReport.xbutton.button == Button4 ? 1.0 : -1.0);
3566 ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3568 else if (aReport.type == ButtonPress)
3570 if (aButton == Aspect_VKeyMouse_LeftButton)
3572 TheIsAnimating = Standard_False;
3574 ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
3578 ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
3580 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3585 Window anXWindow = !VT_GetWindow().IsNull() ? VT_GetWindow()->XWindow() : 0;
3586 if (anXWindow != aReport.xmotion.window)
3591 // remove all the ButtonMotionMask and process them at once
3592 for (int aNbMaxEvents = XPending (aDisplay); aNbMaxEvents > 0; --aNbMaxEvents)
3594 if (!XCheckWindowEvent (aDisplay, anXWindow, ButtonMotionMask | PointerMotionMask, &aReport))
3600 Graphic3d_Vec2i aPos (aReport.xmotion.x, aReport.xmotion.y);
3601 Aspect_VKeyMouse aButtons = Aspect_VKeyMouse_NONE;
3602 Aspect_VKeyFlags aFlags = Aspect_VKeyFlags_NONE;
3603 if ((aReport.xmotion.state & Button1Mask) != 0)
3605 aButtons |= Aspect_VKeyMouse_LeftButton;
3607 else if ((aReport.xmotion.state & Button2Mask) != 0)
3609 aButtons |= Aspect_VKeyMouse_MiddleButton;
3611 else if ((aReport.xmotion.state & Button3Mask) != 0)
3613 aButtons |= Aspect_VKeyMouse_RightButton;
3616 if (aReport.xmotion.state & ControlMask)
3618 aFlags |= Aspect_VKeyFlags_CTRL;
3620 if (aReport.xmotion.state & ShiftMask)
3622 aFlags |= Aspect_VKeyFlags_SHIFT;
3624 if (ViewerTest::CurrentEventManager()->Keys().IsKeyDown (Aspect_VKey_Alt))
3626 aFlags |= Aspect_VKeyFlags_ALT;
3629 ViewerTest::CurrentEventManager()->UpdateMousePosition (aPos, aButtons, aFlags, false);
3630 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3634 return (!toPick || ViewerTest::CurrentEventManager()->ToPickPoint()) ? 1 : 0;
3637 //==============================================================================
3638 //function : VProcessEvents
3639 //purpose : manage the event in the Viewer window (see Tcl_CreateFileHandler())
3640 //==============================================================================
3641 static void VProcessEvents (ClientData theDispX, int)
3643 Display* aDispX = (Display* )theDispX;
3644 Handle(Aspect_DisplayConnection) aDispConn;
3645 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
3646 aDriverIter (ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
3648 const Handle(Aspect_DisplayConnection)& aDispConnTmp = aDriverIter.Key2()->GetDisplayConnection();
3649 if (aDispConnTmp->GetDisplay() == aDispX)
3651 aDispConn = aDispConnTmp;
3655 if (aDispConn.IsNull())
3657 std::cerr << "Error: ViewerTest is unable processing messages for unknown X Display\n";
3661 // process new events in queue
3662 SetDisplayConnection (aDispConn);
3664 for (int aNbEventsMax = XPending (aDispX), anEventIter (0);;)
3666 const int anEventResult = ViewerMainLoop (0, NULL);
3667 if (anEventResult == 0)
3672 aNbRemain = XPending (aDispX);
3673 if (++anEventIter >= aNbEventsMax
3680 // Listening X events through Tcl_CreateFileHandler() callback is fragile,
3681 // it is possible that new events will arrive to queue before the end of this callback
3682 // so that either this callback should go into an infinite loop (blocking processing of other events)
3683 // or to keep unprocessed events till the next queue update (which can arrive not soon).
3684 // Sending a dummy event in this case is a simple workaround (still, it is possible that new event will be queued in-between).
3688 memset (&aDummyEvent, 0, sizeof(aDummyEvent));
3689 aDummyEvent.type = ClientMessage;
3690 aDummyEvent.xclient.format = 32;
3691 XSendEvent (aDispX, InputFocus, False, 0, &aDummyEvent);
3695 if (const Handle(AIS_InteractiveContext)& anActiveCtx = ViewerTest::GetAISContext())
3697 SetDisplayConnection (anActiveCtx->CurrentViewer()->Driver()->GetDisplayConnection());
3702 //==============================================================================
3703 //function : OSWindowSetup
3704 //purpose : Setup for the X11 window to be able to cath the event
3705 //==============================================================================
3708 static void OSWindowSetup()
3710 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
3713 Window window = VT_GetWindow()->XWindow();
3714 SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
3715 Display *aDisplay = GetDisplayConnection()->GetDisplay();
3716 XSynchronize(aDisplay, 1);
3718 // X11 : For keyboard on SUN
3720 wmhints.flags = InputHint;
3723 XSetWMHints( aDisplay, window, &wmhints);
3725 XSelectInput( aDisplay, window, ExposureMask | KeyPressMask | KeyReleaseMask |
3726 ButtonPressMask | ButtonReleaseMask |
3727 StructureNotifyMask |
3729 Button1MotionMask | Button2MotionMask |
3730 Button3MotionMask | FocusChangeMask
3732 Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
3733 XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
3735 XSynchronize(aDisplay, 0);
3743 //==============================================================================
3746 //==============================================================================
3748 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgv)
3750 const Handle(V3d_View) aView = ViewerTest::CurrentView();
3753 std::cout << "Error: no active viewer!\n";
3757 Standard_Boolean toFit = Standard_True;
3758 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
3759 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3761 TCollection_AsciiString anArg (theArgv[anArgIter]);
3763 if (anUpdateTool.parseRedrawMode (anArg))
3767 else if (anArg == "-selected")
3769 ViewerTest::GetAISContext()->FitSelected (aView, 0.01, Standard_False);
3770 toFit = Standard_False;
3774 std::cout << "Syntax error at '" << anArg << "'\n";
3780 aView->FitAll (0.01, Standard_False);
3785 //=======================================================================
3786 //function : VFitArea
3787 //purpose : Fit view to show area located between two points
3788 // : given in world 2D or 3D coordinates.
3789 //=======================================================================
3790 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
3792 Handle(V3d_View) aView = ViewerTest::CurrentView();
3795 std::cerr << theArgVec[0] << "Error: No active view.\n";
3800 gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
3801 gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
3805 aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3806 aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3807 aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
3808 aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
3810 else if (theArgNb == 7)
3812 aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
3813 aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
3814 aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
3815 aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
3816 aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
3817 aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
3821 std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
3822 theDI.PrintHelp(theArgVec[0]);
3826 // Convert model coordinates to view space
3827 Handle(Graphic3d_Camera) aCamera = aView->Camera();
3828 gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
3829 gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
3831 // Determine fit area
3832 gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
3833 gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
3835 Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
3837 if (aDiagonal < Precision::Confusion())
3839 std::cerr << theArgVec[0] << "Error: view area is too small.\n";
3843 aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
3847 //==============================================================================
3849 //purpose : ZFitall, no DRAW arguments
3850 //Draw arg : No args
3851 //==============================================================================
3852 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
3854 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
3856 if (aCurrentView.IsNull())
3858 std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
3864 aCurrentView->ZFitAll();
3865 aCurrentView->Redraw();
3869 Standard_Real aScale = 1.0;
3873 aScale = Draw::Atoi (theArgVec[1]);
3876 aCurrentView->ZFitAll (aScale);
3877 aCurrentView->Redraw();
3882 //==============================================================================
3883 //function : VRepaint
3885 //==============================================================================
3886 static int VRepaint (Draw_Interpretor& , Standard_Integer theArgNb, const char** theArgVec)
3888 Handle(V3d_View) aView = ViewerTest::CurrentView();
3891 std::cout << "Error: no active viewer!\n";
3895 Standard_Boolean isImmediateUpdate = Standard_False;
3896 for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3898 TCollection_AsciiString anArg (theArgVec[anArgIter]);
3900 if (anArg == "-immediate"
3903 isImmediateUpdate = Standard_True;
3904 if (anArgIter + 1 < theArgNb
3905 && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], isImmediateUpdate))
3910 else if (anArg == "-continuous"
3913 || anArg == "-framerate")
3915 Standard_Real aFps = -1.0;
3916 if (anArgIter + 1 < theArgNb
3917 && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
3919 aFps = Draw::Atof (theArgVec[++anArgIter]);
3922 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
3923 if (Abs (aFps) >= 1.0)
3925 aRedrawer.Start (aView->Window(), aFps);
3934 std::cout << "Syntax error at '" << anArg << "'\n";
3939 if (isImmediateUpdate)
3941 aView->RedrawImmediate();
3950 //==============================================================================
3952 //purpose : Remove all the object from the viewer
3953 //Draw arg : No args
3954 //==============================================================================
3956 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
3958 Handle(V3d_View) V = ViewerTest::CurrentView();
3960 ViewerTest::Clear();
3964 //==============================================================================
3967 //==============================================================================
3969 static int VPick (Draw_Interpretor& ,
3970 Standard_Integer theNbArgs,