0031505: Point Cloud Rendering - fix on-screen statistics about number of visible...
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
CommitLineData
b311480e 1// Created on: 1998-09-01
2// Created by: Robert COUBLANC
3// Copyright (c) 1998-1999 Matra Datavision
973c2be1 4// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 5//
973c2be1 6// This file is part of Open CASCADE Technology software library.
b311480e 7//
d5f74e42 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
973c2be1 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.
b311480e 13//
973c2be1 14// Alternatively, this file may be used under the terms of Open CASCADE
15// commercial license or contractual agreement.
b311480e 16
58655684 17#include <OpenGl_GlCore20.hxx>
49582f9d 18#include <ViewerTest.hxx>
1beb58d7 19
1beb58d7 20#include <AIS_AnimationCamera.hxx>
21#include <AIS_AnimationObject.hxx>
30a1b24e 22#include <AIS_CameraFrustum.hxx>
7a324550 23#include <AIS_ColorScale.hxx>
49582f9d 24#include <AIS_InteractiveContext.hxx>
0a768f56 25#include <AIS_ListOfInteractive.hxx>
26#include <AIS_ListIteratorOfListOfInteractive.hxx>
49582f9d 27#include <AIS_Manipulator.hxx>
2108d9a2 28#include <AIS_ViewCube.hxx>
49582f9d 29#include <AIS_Shape.hxx>
30#include <Aspect_DisplayConnection.hxx>
8a590580 31#include <Aspect_Grid.hxx>
49582f9d 32#include <Aspect_TypeOfLine.hxx>
33#include <Draw.hxx>
34#include <Draw_Appli.hxx>
35#include <Draw_Interpretor.hxx>
08f8a185 36#include <Draw_ProgressIndicator.hxx>
49582f9d 37#include <gp_Dir.hxx>
38#include <gp_Pln.hxx>
39#include <gp_Pnt.hxx>
61b0191c 40#include <Graphic3d_ArrayOfPolylines.hxx>
49582f9d 41#include <Graphic3d_AspectFillArea3d.hxx>
2bd4c032 42#include <Graphic3d_AspectMarker3d.hxx>
49582f9d 43#include <Graphic3d_ClipPlane.hxx>
077a220c 44#include <Graphic3d_CubeMapPacked.hxx>
45#include <Graphic3d_CubeMapSeparate.hxx>
a79f67f8 46#include <Graphic3d_GraduatedTrihedron.hxx>
49582f9d 47#include <Graphic3d_NameOfTextureEnv.hxx>
48#include <Graphic3d_Texture2Dmanual.hxx>
269294d6 49#include <Graphic3d_TextureEnv.hxx>
50#include <Graphic3d_TextureParams.hxx>
51#include <Graphic3d_TypeOfTextureFilter.hxx>
49582f9d 52#include <Image_AlienPixMap.hxx>
53#include <Image_Diff.hxx>
54#include <Image_VideoRecorder.hxx>
08f8a185 55#include <Message_ProgressSentry.hxx>
49582f9d 56#include <NCollection_DataMap.hxx>
18d715bd 57#include <NCollection_List.hxx>
58#include <NCollection_Vector.hxx>
8693dfd0 59#include <OSD.hxx>
208e6839 60#include <OSD_Timer.hxx>
49582f9d 61#include <OpenGl_GraphicDriver.hxx>
4269bd1b 62#include <Prs3d_ShadingAspect.hxx>
6262338c 63#include <Prs3d_Drawer.hxx>
61b0191c 64#include <Prs3d_LineAspect.hxx>
65#include <Prs3d_Root.hxx>
fd3f6bd0 66#include <Prs3d_Text.hxx>
67#include <Select3D_SensitivePrimitiveArray.hxx>
49582f9d 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>
7fd59977 83
293211ae 84#include <tcl.h>
85
692613e5 86#include <cstdlib>
25289ec1 87
58655684 88#if defined(_WIN32)
4fe56619 89 #include <WNT_WClass.hxx>
90 #include <WNT_Window.hxx>
4fe56619 91#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
4fe56619 92 #include <Cocoa_Window.hxx>
7fd59977 93#else
4fe56619 94 #include <Xw_Window.hxx>
95 #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
96 #include <X11/Xutil.h>
97 #include <tk.h>
7fd59977 98#endif
99
7fd59977 100//==============================================================================
101// VIEWER GLOBAL VARIABLES
102//==============================================================================
103
104Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
b514beda 105Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
7fd59977 106
107Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
4754e164 108extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
7fd59977 109
58655684 110#if defined(_WIN32)
7fd59977 111static Handle(WNT_Window)& VT_GetWindow() {
112 static Handle(WNT_Window) WNTWin;
113 return WNTWin;
114}
4fe56619 115#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
4fe56619 116static Handle(Cocoa_Window)& VT_GetWindow()
117{
118 static Handle(Cocoa_Window) aWindow;
119 return aWindow;
120}
121extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
18d715bd 122extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
123
7fd59977 124#else
7fd59977 125static Handle(Xw_Window)& VT_GetWindow(){
126 static Handle(Xw_Window) XWWin;
127 return XWWin;
128}
7fd59977 129
130static void VProcessEvents(ClientData,int);
131#endif
132
18d715bd 133static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
134{
135 static Handle(Aspect_DisplayConnection) aDisplayConnection;
136 return aDisplayConnection;
137}
138
139static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
140{
141 GetDisplayConnection() = theDisplayConnection;
142}
143
18d715bd 144NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
58655684 145static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)> ViewerTest_myContexts;
18d715bd 146static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
58655684 147static OpenGl_Caps ViewerTest_myDefaultCaps;
18d715bd 148
7fd59977 149static void OSWindowSetup();
150
f42753ed 151static struct
152{
153 Quantity_Color FlatColor;
154 Quantity_Color GradientColor1;
155 Quantity_Color GradientColor2;
156 Aspect_GradientFillMethod FillMethod;
157} ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
158
7fd59977 159//==============================================================================
160// EVENT GLOBAL VARIABLES
161//==============================================================================
162
1beb58d7 163Standard_Boolean TheIsAnimating = Standard_False;
7fd59977 164
293211ae 165namespace
166{
167
168 //! Checks if some set is a subset of other set
169 //! @tparam TheSuperSet the type of the superset
170 //! @tparam TheSubSet the type of the subset
171 //! @param theSuperSet the superset
172 //! @param theSubSet the subset to be checked
173 //! @return true if the superset includes subset, or false otherwise
174 template <typename TheSuperSet, typename TheSubSet>
175 static bool includes (const TheSuperSet& theSuperSet, const TheSubSet& theSubSet)
176 {
177 return std::includes (theSuperSet.begin(), theSuperSet.end(), theSubSet.begin(), theSubSet.end());
178 }
179
180 //! A variable set of keys for command-line options.
181 //! It includes a set of mandatory keys and a set of all possible keys.
182 class CommandOptionKeyVariableSet
183 {
184 public:
185 //! Default constructor
186 CommandOptionKeyVariableSet()
187 {
188 }
189
190 //! Constructor
191 //! @param theMandatoryKeySet the set of the mandatory option keys
192 //! @param theAdditionalKeySet the set of additional options that could be omitted
193 CommandOptionKeyVariableSet (
194 const ViewerTest_CommandOptionKeySet& theMandatoryKeySet,
195 const ViewerTest_CommandOptionKeySet& theAdditionalKeySet = ViewerTest_CommandOptionKeySet())
196 : myMandatoryKeySet (theMandatoryKeySet)
197 {
198 std::set_union (theMandatoryKeySet.begin(),
199 theMandatoryKeySet.end(),
200 theAdditionalKeySet.begin(),
201 theAdditionalKeySet.end(),
202 std::inserter (myFullKeySet, myFullKeySet.begin()));
203 }
204
205 //! Checks if the set of option keys fits to the current variable set (it must contain all mandatory keys
206 //! and be contained in the full key set)
207 //! @param theCheckedKeySet the set of option keys to be checked
208 bool IsInSet (const ViewerTest_CommandOptionKeySet& theCheckedKeySet) const
209 {
210 return includes (theCheckedKeySet, myMandatoryKeySet) && includes (myFullKeySet, theCheckedKeySet);
211 }
212
213 private:
214 //! A set of mandatory command-line option keys
215 ViewerTest_CommandOptionKeySet myMandatoryKeySet;
216
217 //! A full set of command-line option keys (includes mandatory and additional option keys)
218 ViewerTest_CommandOptionKeySet myFullKeySet;
219 };
220
221 //! Gets some code by its name
222 //! @tparam TheCode the type of a code to be found
223 //! @param theCodeNameMap the map from code names to codes
224 //! @param theCodeName the name of a code to be found
225 //! @param theCode the code to be found
226 //! @return true if a code is found, or false otherwise
227 template <typename TheCode>
228 static bool getSomeCodeByName (const std::map<TCollection_AsciiString, TheCode>& theCodeNameMap,
229 TCollection_AsciiString theCodeName,
230 TheCode& theCode)
231 {
232 theCodeName.LowerCase();
233 const typename std::map<TCollection_AsciiString, TheCode>::const_iterator aCodeIterator = theCodeNameMap.find (
234 theCodeName);
235 if (aCodeIterator == theCodeNameMap.end())
236 {
237 return false;
238 }
239 theCode = aCodeIterator->second;
240 return true;
241 }
242
243 // Defines possible commands related to background changing
244 enum BackgroundCommand
245 {
077a220c 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
293211ae 253 };
254
255 //! Map from background command names to its codes
256 typedef std::map<TCollection_AsciiString, BackgroundCommand> BackgroundCommandNameMap;
257
258 //! Creates a map from background command names to its codes
259 //! @return a map from background command names to its codes
260 static BackgroundCommandNameMap createBackgroundCommandNameMap()
261 {
262 BackgroundCommandNameMap aBackgroundCommandNameMap;
077a220c 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;
293211ae 270 return aBackgroundCommandNameMap;
271 }
272
273 //! Gets a background command by its name
274 //! @param theBackgroundCommandName the name of the background command
275 //! @param theBackgroundCommand the background command to be found
276 //! @return true if a background command is found, or false otherwise
277 static bool getBackgroundCommandByName (const TCollection_AsciiString& theBackgroundCommandName,
278 BackgroundCommand& theBackgroundCommand)
279 {
280 static const BackgroundCommandNameMap THE_BACKGROUND_COMMAND_NAME_MAP = createBackgroundCommandNameMap();
281 return getSomeCodeByName (THE_BACKGROUND_COMMAND_NAME_MAP, theBackgroundCommandName, theBackgroundCommand);
282 }
283
284 //! Map from background image fill method names to its codes
285 typedef std::map<TCollection_AsciiString, Aspect_FillMethod> BackgroundImageFillMethodNameMap;
286
287 //! Creates a map from background image fill method names to its codes
288 //! @return a map from background image fill method names to its codes
289 static BackgroundImageFillMethodNameMap createBackgroundImageFillMethodNameMap()
290 {
291 BackgroundImageFillMethodNameMap aBackgroundImageFillMethodNameMap;
292 aBackgroundImageFillMethodNameMap["none"] = Aspect_FM_NONE;
293 aBackgroundImageFillMethodNameMap["centered"] = Aspect_FM_CENTERED;
294 aBackgroundImageFillMethodNameMap["tiled"] = Aspect_FM_TILED;
295 aBackgroundImageFillMethodNameMap["stretch"] = Aspect_FM_STRETCH;
296 return aBackgroundImageFillMethodNameMap;
297 }
298
299 //! Gets a background image fill method by its name
300 //! @param theBackgroundImageFillMethodName the name of the background image fill method
301 //! @param theBackgroundImageFillMethod the background image fill method to be found
302 //! @return true if a background image fill method is found, or false otherwise
303 static bool getBackgroundImageFillMethodByName (const TCollection_AsciiString& theBackgroundImageFillMethodName,
304 Aspect_FillMethod& theBackgroundImageFillMethod)
305 {
306 static const BackgroundImageFillMethodNameMap THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP =
307 createBackgroundImageFillMethodNameMap();
308 return getSomeCodeByName (THE_BACKGROUND_IMAGE_FILL_METHOD_NAME_MAP,
309 theBackgroundImageFillMethodName,
310 theBackgroundImageFillMethod);
311 }
312
313 //! Map from background gradient fill method names to its codes
314 typedef std::map<TCollection_AsciiString, Aspect_GradientFillMethod> BackgroundGradientFillMethodNameMap;
315
316 //! Creates a map from background gradient fill method names to its codes
317 //! @return a map from background gradient fill method names to its codes
318 static BackgroundGradientFillMethodNameMap createBackgroundGradientFillMethodNameMap()
319 {
320 BackgroundGradientFillMethodNameMap aBackgroundGradientFillMethodNameMap;
321 aBackgroundGradientFillMethodNameMap["none"] = Aspect_GFM_NONE;
322 aBackgroundGradientFillMethodNameMap["hor"] = Aspect_GFM_HOR;
323 aBackgroundGradientFillMethodNameMap["horizontal"] = Aspect_GFM_HOR;
324 aBackgroundGradientFillMethodNameMap["ver"] = Aspect_GFM_VER;
325 aBackgroundGradientFillMethodNameMap["vertical"] = Aspect_GFM_VER;
326 aBackgroundGradientFillMethodNameMap["diag1"] = Aspect_GFM_DIAG1;
327 aBackgroundGradientFillMethodNameMap["diagonal1"] = Aspect_GFM_DIAG1;
328 aBackgroundGradientFillMethodNameMap["diag2"] = Aspect_GFM_DIAG2;
329 aBackgroundGradientFillMethodNameMap["diagonal2"] = Aspect_GFM_DIAG2;
330 aBackgroundGradientFillMethodNameMap["corner1"] = Aspect_GFM_CORNER1;
331 aBackgroundGradientFillMethodNameMap["corner2"] = Aspect_GFM_CORNER2;
332 aBackgroundGradientFillMethodNameMap["corner3"] = Aspect_GFM_CORNER3;
333 aBackgroundGradientFillMethodNameMap["corner4"] = Aspect_GFM_CORNER4;
334 return aBackgroundGradientFillMethodNameMap;
335 }
336
337 //! Gets a gradient fill method by its name
338 //! @param theBackgroundGradientFillMethodName the name of the gradient fill method
339 //! @param theBackgroundGradientFillMethod the gradient fill method to be found
340 //! @return true if a gradient fill method is found, or false otherwise
341 static bool getBackgroundGradientFillMethodByName (const TCollection_AsciiString& theBackgroundGradientFillMethodName,
342 Aspect_GradientFillMethod& theBackgroundGradientFillMethod)
343 {
344 static const BackgroundGradientFillMethodNameMap THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP =
345 createBackgroundGradientFillMethodNameMap();
346 return getSomeCodeByName (THE_BACKGROUND_GRADIENT_FILL_METHOD_NAME_MAP,
347 theBackgroundGradientFillMethodName,
348 theBackgroundGradientFillMethod);
349 }
350
351 //! Changes the background in accordance with passed command line options
352 class BackgroundChanger
353 {
354 public:
355 //! Constructor. Prepares the command parser
356 BackgroundChanger()
357 {
358 prepareCommandParser();
359 }
360
361 //! Processes the command line and changes the background
362 //! @param theDrawInterpretor the interpreter of the Draw Harness application
363 //! @param theNumberOfCommandLineArguments the number of passed command line arguments
364 //! @param theCommandLineArguments the array of command line arguments
365 bool ProcessCommandLine (Draw_Interpretor& theDrawInterpretor,
366 const Standard_Integer theNumberOfCommandLineArguments,
367 const char* const* const theCommandLineArguments)
368 {
369 const char* const aBackgroundCommandName = theCommandLineArguments[0];
370 BackgroundCommand aBackgroundCommand = BackgroundCommand_Main;
371 if (!getBackgroundCommandByName (aBackgroundCommandName, aBackgroundCommand))
372 {
373 return false;
374 }
375 addCommandDescription (aBackgroundCommand);
376 myCommandParser.Parse (theNumberOfCommandLineArguments, theCommandLineArguments);
377 return processCommandOptions (aBackgroundCommandName, aBackgroundCommand, theDrawInterpretor);
378 }
379
380 private:
381 //! The type of functions that are able to set gradient background filling
382 typedef void SetGradientFunction (const Quantity_Color& /* theColor1 */,
383 const Quantity_Color& /* theColor2 */,
384 const Aspect_GradientFillMethod /* theGradientMode */);
385
386 //! The type of functions that are able to fill a background with a specific color
387 typedef void SetColorFunction (const Quantity_Color& /* theColor */);
388
389 //! the command parser used to parse command line options and its arguments
390 ViewerTest_CmdParser myCommandParser;
391
392 //! the option key for the command that sets an image as a background
393 ViewerTest_CommandOptionKey myImageOptionKey;
394
395 //! the option key for the command that sets a background image fill type
396 ViewerTest_CommandOptionKey myImageModeOptionKey;
397
398 //! the option key for the command that sets a gradient filling for the background
399 ViewerTest_CommandOptionKey myGradientOptionKey;
400
401 //! the option key for the command that sets a background gradient filling method
402 ViewerTest_CommandOptionKey myGradientModeOptionKey;
403
404 //! the option key for the command that fills background with a specific color
405 ViewerTest_CommandOptionKey myColorOptionKey;
406
407 //! the option key for the command that sets default background gradient or color
408 ViewerTest_CommandOptionKey myDefaultOptionKey;
409
077a220c 410 //! the option key for the command that sets an environment cubemap as a background
411 ViewerTest_CommandOptionKey myCubeMapOptionKey;
412
413 //! the option key for the command that defines order of tiles in one image packed cubemap
414 ViewerTest_CommandOptionKey myCubeMapOrderOptionKey;
415
416 //! the option key for the command that sets inversion of Z axis for background cubemap
417 ViewerTest_CommandOptionKey myCubeMapInvertedZOptionKey;
418
67312b79 419 //! the option key for the command that allows skip IBL map generation
420 ViewerTest_CommandOptionKey myCubeMapDoNotGenPBREnvOptionKey;
421
293211ae 422 //! the variable set of options that are allowed for the old scenario (without any option passed)
423 CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
424
077a220c 425 //! the variable set of options that are allowed for setting an environment cubemap as background
426 CommandOptionKeyVariableSet myCubeMapOptionVariableSet;
427
293211ae 428 //! the variable set of options that are allowed for setting an image as a background
429 CommandOptionKeyVariableSet myImageOptionVariableSet;
430
431 //! the variable set of options that are allowed for setting a background image fill type
432 CommandOptionKeyVariableSet myImageModeOptionVariableSet;
433
434 //! the variable set of options that are allowed for setting a gradient filling for the background
435 CommandOptionKeyVariableSet myGradientOptionVariableSet;
436
437 //! the variable set of options that are allowed for setting a background gradient filling method
438 CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
439
440 //! the variable set of options that are allowed for filling a background with a specific color
441 CommandOptionKeyVariableSet myColorOptionVariableSet;
442
443 //! the variable set of options that are allowed for setting a default background gradient
444 CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
445
446 //! the variable set of options that are allowed for setting a default background color
447 CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
448
449 //! the variable set of options that are allowed for printing help
450 CommandOptionKeyVariableSet myHelpOptionVariableSet;
451
452 //! Adds options to command parser
453 void addOptionsToCommandParser()
454 {
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");
077a220c 467
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");
67312b79 472 myCubeMapDoNotGenPBREnvOptionKey = myCommandParser.AddOption ("nopbrenv", "whether IBL map generation should be skipped");
293211ae 473 }
474
475 //! Creates option sets used to determine if a passed option set is valid or not
476 void createOptionSets()
477 {
478 ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
479 anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
480 myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
481
077a220c 482 ViewerTest_CommandOptionKeySet aCubeMapOptionSet;
483 aCubeMapOptionSet.insert (myCubeMapOptionKey);
484 ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
485 aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
67312b79 486 aCubeMapAdditionalOptionKeySet.insert (myCubeMapDoNotGenPBREnvOptionKey);
077a220c 487 aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
488 myCubeMapOptionVariableSet = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
489
293211ae 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);
496
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);
503
504 ViewerTest_CommandOptionKeySet aColorOptionSet;
505 aColorOptionSet.insert (myColorOptionKey);
506 myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
507
508 aGradientOptionSet.insert (myDefaultOptionKey);
509 myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
510 aColorOptionSet.insert (myDefaultOptionKey);
511 myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
512
513 ViewerTest_CommandOptionKeySet aHelpOptionSet;
514 aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
515 myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
516 }
517
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()
521 {
522 addOptionsToCommandParser();
523 createOptionSets();
524 }
525
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)
529 {
530 std::string aDescription;
531 bool isMainCommand = false;
532 switch (theBackgroundCommand)
533 {
534 case BackgroundCommand_Main:
535 aDescription = "Command: vbackground (changes background or some background settings)";
536 isMainCommand = true;
537 break;
538 case BackgroundCommand_Image:
539 aDescription = "Command: vsetbg (loads image as a background)";
540 break;
541 case BackgroundCommand_ImageMode:
542 aDescription = "Command: vsetbgmode (changes background fill type)";
543 break;
544 case BackgroundCommand_Gradient:
545 aDescription = "Command: vsetgradientbg (mounts gradient background)";
546 break;
547 case BackgroundCommand_GradientMode:
548 aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
549 break;
550 case BackgroundCommand_Color:
551 aDescription = "Command: vsetcolorbg (sets color background)";
552 break;
553 case BackgroundCommand_Default:
554 aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
555 break;
556 default:
557 return;
558 }
559 if (!isMainCommand)
560 {
561 aDescription += "\nThis command is obsolete. Use vbackground instead.";
562 }
563 myCommandParser.SetDescription (aDescription);
564 }
565
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
570 {
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;
579 }
580
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)
587 {
588 const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
589 if (anAISContext.IsNull())
590 {
591 theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
592 return false;
593 }
594 return true;
595 }
596
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
605 {
606 if (myCommandParser.HasNoOption())
607 {
608 return printHelp (theBackgroundCommandName, theDrawInterpretor);
609 }
610 if (checkViewerIsNeeded (theBackgroundCommand)
611 && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
612 {
613 return false;
614 }
615 if (myCommandParser.HasOnlyUnnamedOption())
616 {
617 return processUnnamedOption (theBackgroundCommand);
618 }
619 return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
620 }
621
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
626 {
627 switch (theBackgroundCommand)
628 {
629 case BackgroundCommand_Main:
630 return false;
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();
643 default:
644 return false;
645 }
646 }
647
648 //! Processes the image unnamed option
649 //! @return true if processing was successful, or false otherwise
650 bool processImageUnnamedOption() const
651 {
652 const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
653 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
654 if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
655 {
656 return false;
657 }
658 std::string anImageFileName;
659 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
660 {
661 return false;
662 }
663 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
664 if (aNumberOfImageUnnamedOptionArguments == 2)
665 {
666 std::string anImageModeString;
667 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
668 {
669 return false;
670 }
671 if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
672 {
673 return false;
674 }
675 }
676 setImage (anImageFileName.c_str(), anImageMode);
677 return true;
678 }
679
680 //! Processes the image mode unnamed option
681 //! @return true if processing was successful, or false otherwise
682 bool processImageModeUnnamedOption() const
683 {
684 return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
685 }
686
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
691 {
692 const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
693 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
694 if (aNumberOfGradientUnnamedOptionArguments < 2)
695 {
696 return false;
697 }
698
699 Standard_Integer anArgumentIndex = 0;
700 Quantity_Color aColor1;
701 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
702 {
703 return false;
704 }
705 if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
706 {
707 return false;
708 }
709
710 Quantity_Color aColor2;
711 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
712 {
713 return false;
714 }
715 if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
716 {
717 return false;
718 }
719
720 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
721 if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
722 {
723 std::string anGradientModeString;
724
725 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
726 anArgumentIndex,
727 anGradientModeString))
728 {
729 return false;
730 }
731 if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
732 {
733 return false;
734 }
735 ++anArgumentIndex;
736 }
737 if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
738 {
739 return false;
740 }
741 theSetGradient (aColor1, aColor2, aGradientMode);
742 return true;
743 }
744
745 //! Processes the gradient mode unnamed option
746 //! @return true if processing was successful, or false otherwise
747 bool processGradientModeUnnamedOption() const
748 {
749 return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
750 }
751
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
756 {
757 return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
758 }
759
760 //! Processes the default back unnamed option
761 //! @return true if processing was successful, or false otherwise
762 bool processDefaultUnnamedOption() const
763 {
764 if (processGradientUnnamedOption (setDefaultGradient))
765 {
766 return true;
767 }
768 return processColorUnnamedOption (setDefaultColor);
769 }
770
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
779 {
780 const bool isMain = (theBackgroundCommand == BackgroundCommand_Main);
781 const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
077a220c 782 if (myCubeMapOptionVariableSet.IsInSet (aUsedOptions) && isMain)
783 {
784 return processCubeMapOptionSet();
785 }
293211ae 786 if (myImageOptionVariableSet.IsInSet (aUsedOptions)
787 && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
788 {
789 return processImageOptionSet();
790 }
791 if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
792 && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
793 {
794 return processImageModeOptionSet();
795 }
796 if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
797 && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
798 {
799 return processGradientOptionSet();
800 }
801 if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
802 && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
803 {
804 return processGradientModeOptionSet();
805 }
806 if (myColorOptionVariableSet.IsInSet (aUsedOptions)
807 && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
808 {
809 return processColorOptionSet();
810 }
811 if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
812 || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
813 && (theBackgroundCommand == BackgroundCommand_Default)))
814 {
815 return processDefaultGradientOptionSet();
816 }
817 if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
818 || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
819 {
820 return processDefaultColorOptionSet();
821 }
822 if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
823 {
824 return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
825 }
826 return false;
827 }
828
077a220c 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
832 {
833 NCollection_Array1<TCollection_AsciiString> aFilePaths;
834
835 if (!processCubeMapOptions (aFilePaths))
836 {
837 return false;
838 }
839
840 Graphic3d_CubeMapOrder anOrder = Graphic3d_CubeMapOrder::Default();
841
842 if (myCommandParser.HasOption (myCubeMapOrderOptionKey))
843 {
844 if (!processCubeMapOrderOptions (anOrder))
845 {
846 return false;
847 }
848 }
849
850 bool aZIsInverted = false;
851 if (myCommandParser.HasOption (myCubeMapInvertedZOptionKey))
852 {
853 if (!processCubeMapInvertedZOptionSet())
854 {
855 return false;
856 }
857 aZIsInverted = true;
858 }
859
67312b79 860 bool aToGenPBREnv = true;
861 if (myCommandParser.HasOption (myCubeMapDoNotGenPBREnvOptionKey))
862 {
863 if (!processCubeMapDoNotGenPBREnvOptionSet())
864 {
865 return false;
866 }
867 aToGenPBREnv = false;
868 }
869
870 setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted, aToGenPBREnv);
077a220c 871 return true;
872 }
873
293211ae 874 //! Processes the image option set
875 //! @return true if processing was successful, or false otherwise
876 bool processImageOptionSet() const
877 {
878 std::string anImageFileName;
879 if (!processImageOption (anImageFileName))
880 {
881 return false;
882 }
883 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
884 if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
885 {
886 return false;
887 }
888 setImage (anImageFileName.c_str(), anImageMode);
889 return true;
890 }
891
892 //! Processes the image mode option set
893 //! @return true if processing was successful, or false otherwise
894 bool processImageModeOptionSet() const
895 {
896 return processImageModeOptionSet (myImageModeOptionKey);
897 }
898
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
903 {
904 Aspect_FillMethod anImageMode = Aspect_FM_NONE;
905 if (!processImageModeOption (theImageModeOptionKey, anImageMode))
906 {
907 return false;
908 }
909 setImageMode (anImageMode);
910 return true;
911 }
912
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
917 {
918 Quantity_Color aColor1;
919 Quantity_Color aColor2;
920 if (!processGradientOption (aColor1, aColor2))
921 {
922 return false;
923 }
924 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
925 if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
926 {
927 return false;
928 }
929 theSetGradient (aColor1, aColor2, aGradientMode);
930 return true;
931 }
932
933 //! Processes the gradient mode option set
934 //! @return true if processing was successful, or false otherwise
935 bool processGradientModeOptionSet() const
936 {
937 return processGradientModeOptionSet (myGradientModeOptionKey);
938 }
939
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
944 {
945 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
946 if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
947 {
948 return false;
949 }
950 setGradientMode (aGradientMode);
951 return true;
952 }
953
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
958 {
959 return processColorOptionSet (myColorOptionKey, theSetColor);
960 }
961
962 //! Processes the default color option set
963 //! @return true if processing was successful, or false otherwise
964 bool processDefaultGradientOptionSet() const
965 {
966 return processGradientOptionSet (setDefaultGradient);
967 }
968
969 //! Processes the default gradient option set
970 //! @return true if processing was successful, or false otherwise
971 bool processDefaultColorOptionSet() const
972 {
973 return processColorOptionSet (setDefaultColor);
974 }
975
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
982 {
983 Quantity_Color aColor;
984 if (!processColorOption (theColorOptionKey, aColor))
985 {
986 return false;
987 }
988 theSetColor (aColor);
989 return true;
990 }
991
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
997 {
998 const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
999 ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
1000 if (aNumberOfHelpOptionArguments != 0)
1001 {
1002 return false;
1003 }
1004 return printHelp (theBackgroundCommandName, theDrawInterpretor);
1005 }
1006
077a220c 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
1011 {
1012 const Standard_Integer aNumberOfCubeMapOptionArguments = myCommandParser.GetNumberOfOptionArguments (myCubeMapOptionKey);
1013
1014 if (aNumberOfCubeMapOptionArguments != 1
1015 && aNumberOfCubeMapOptionArguments != 6)
1016 {
1017 return false;
1018 }
1019
1020 theFilePaths.Resize(0, aNumberOfCubeMapOptionArguments - 1, Standard_False);
1021
1022 for (int i = 0; i < aNumberOfCubeMapOptionArguments; ++i)
1023 {
1024 std::string aCubeMapFileName;
1025 if (!myCommandParser.Arg (myCubeMapOptionKey, i, aCubeMapFileName))
1026 {
1027 return false;
1028 }
1029 theFilePaths[i] = aCubeMapFileName.c_str();
1030 }
1031
1032 return true;
1033 }
1034
67312b79 1035 //! Processes the inverted z cubemap option
077a220c 1036 //! @return true if processing was successful, or false otherwise
1037 bool processCubeMapInvertedZOptionSet () const
1038 {
1039 const Standard_Integer aNumberOfCubeMapZInversionOptionArguments =
1040 myCommandParser.GetNumberOfOptionArguments (myCubeMapInvertedZOptionKey);
1041
1042 if (aNumberOfCubeMapZInversionOptionArguments != 0)
1043 {
1044 return false;
1045 }
1046
1047 return true;
1048 }
1049
67312b79 1050 //! Processes the option allowing to skip IBM maps generation
1051 //! @return true if processing was successful, or false otherwise
1052 bool processCubeMapDoNotGenPBREnvOptionSet() const
1053 {
1054 const Standard_Integer aNumberOfCubeMapDoNotGenPBREnvOptionArguments =
1055 myCommandParser.GetNumberOfOptionArguments(myCubeMapDoNotGenPBREnvOptionKey);
1056
1057 if (aNumberOfCubeMapDoNotGenPBREnvOptionArguments != 0)
1058 {
1059 return false;
1060 }
1061
1062 return true;
1063 }
1064
077a220c 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
1069 {
1070 const Standard_Integer aNumberOfCubeMapOrderOptionArguments = myCommandParser.GetNumberOfOptionArguments(
1071 myCubeMapOrderOptionKey);
1072
1073 if (aNumberOfCubeMapOrderOptionArguments != 6)
1074 {
1075 return false;
1076 }
1077
1078
1079 for (unsigned int i = 0; i < 6; ++i)
1080 {
1081 std::string anOrderItem;
1082 if (!myCommandParser.Arg (myCubeMapOrderOptionKey, i, anOrderItem))
1083 {
1084 return false;
1085 }
1086
1087 theOrder.Set (Graphic3d_CubeMapSide (i),
1088 static_cast<unsigned char> (Draw::Atoi (anOrderItem.c_str())));
1089 }
1090
1091 return theOrder.IsValid();
1092 }
1093
293211ae 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
1098 {
1099 const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1100 myImageOptionKey);
1101 if (aNumberOfImageOptionArguments != 1)
1102 {
1103 return false;
1104 }
1105 std::string anImageFileName;
1106 if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1107 {
1108 return false;
1109 }
1110 theImageFileName = anImageFileName;
1111 return true;
1112 }
1113
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
1118 {
1119 return processImageModeOption (myImageModeOptionKey, theImageMode);
1120 }
1121
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
1128 {
1129 return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1130 }
1131
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
1137 {
1138 Standard_Integer anArgumentIndex = 0;
1139 Quantity_Color aColor1;
1140 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1141 {
1142 return false;
1143 }
1144 Quantity_Color aColor2;
1145 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1146 {
1147 return false;
1148 }
1149 const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1150 myGradientOptionKey);
1151 if (anArgumentIndex != aNumberOfGradientOptionArguments)
1152 {
1153 return false;
1154 }
1155 theColor1 = aColor1;
1156 theColor2 = aColor2;
1157 return true;
1158 }
1159
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
1164 {
1165 return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1166 }
1167
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
1174 {
1175 return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1176 }
1177
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
1188 {
1189 const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1190 theModeOptionKey);
1191 if (aNumberOfModeOptionArguments != 1)
1192 {
1193 return false;
1194 }
1195 std::string aModeString;
1196 if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1197 {
1198 return false;
1199 }
1200 TheMode aMode = TheMode();
1201 if (!theGetModeByName (aModeString.c_str(), aMode))
1202 {
1203 return false;
1204 }
1205 theMode = aMode;
1206 return true;
1207 }
1208
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
1213 {
1214 return processColorOption (myColorOptionKey, theColor);
1215 }
1216
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
1222 {
1223 Standard_Integer anArgumentIndex = 0;
1224 Quantity_Color aColor;
1225 if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1226 {
1227 return false;
1228 }
1229 const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1230 theColorOptionKey);
1231 if (anArgumentIndex != aNumberOfColorOptionArguments)
1232 {
1233 return false;
1234 }
1235 theColor = aColor;
1236 return true;
1237 }
1238
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)
1244 {
1245 return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1246 }
1247
077a220c 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(),
67312b79 1253 bool theZIsInverted = false,
1254 bool theToGenPBREnv = true)
077a220c 1255 {
1256 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
1257 Handle(Graphic3d_CubeMap) aCubeMap;
1258
1259 if (theFileNames.Size() == 1)
1260 aCubeMap = new Graphic3d_CubeMapPacked(theFileNames[0], theOrder);
1261 else
1262 aCubeMap = new Graphic3d_CubeMapSeparate(theFileNames);
1263
1264 aCubeMap->SetZInversion (theZIsInverted);
1265
1266 aCubeMap->GetParams()->SetFilter(Graphic3d_TOTF_BILINEAR);
1267 aCubeMap->GetParams()->SetRepeat(Standard_False);
1268 aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
1269
67312b79 1270 aCurrentView->SetBackgroundCubeMap (aCubeMap, theToGenPBREnv, Standard_True);
077a220c 1271 }
1272
293211ae 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)
1277 {
1278 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1279 aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1280 }
1281
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)
1285 {
1286 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1287 aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1288 }
1289
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)
1297 {
1298 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1299 aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1300 }
1301
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)
1305 {
1306 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1307 aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1308 }
1309
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)
1313 {
1314 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1315 aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1316 aCurrentView->SetBackgroundColor (theColor);
1317 aCurrentView->Update();
1318 }
1319
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)
1327 {
1328 ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1329 ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1330 ViewerTest_DefaultBackground.FillMethod = theGradientMode;
1331 setDefaultGradient();
1332 }
1333
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)
1337 {
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();
1343 setDefaultColor();
1344 }
1345
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()
1349 {
1350 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1351 anInteractiveContextIterator (ViewerTest_myContexts);
1352 anInteractiveContextIterator.More();
1353 anInteractiveContextIterator.Next())
1354 {
1355 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1356 aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1357 ViewerTest_DefaultBackground.GradientColor2,
1358 ViewerTest_DefaultBackground.FillMethod);
1359 }
1360 }
1361
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()
1365 {
1366 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1367 anInteractiveContextIterator (ViewerTest_myContexts);
1368 anInteractiveContextIterator.More();
1369 anInteractiveContextIterator.Next())
1370 {
1371 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1372 aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1373 }
1374 }
1375 };
1376
1377} // namespace
b12e1c7b 1378
7fd59977 1379//==============================================================================
1380
57c28b61 1381#ifdef _WIN32
7fd59977 1382static LRESULT WINAPI ViewerWindowProc(
1383 HWND hwnd,
1384 UINT uMsg,
1385 WPARAM wParam,
1386 LPARAM lParam );
1387static LRESULT WINAPI AdvViewerWindowProc(
1388 HWND hwnd,
1389 UINT uMsg,
1390 WPARAM wParam,
1391 LPARAM lParam );
1392#endif
1393
1394
1395//==============================================================================
1396//function : WClass
1397//purpose :
1398//==============================================================================
1399
1bd04b5a 1400const Handle(WNT_WClass)& ViewerTest::WClass()
7fd59977 1401{
1bd04b5a 1402 static Handle(WNT_WClass) theWClass;
58655684 1403#if defined(_WIN32)
4fe56619 1404 if (theWClass.IsNull())
1405 {
7c65581d 1406 theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
ad03c234 1407 CS_VREDRAW | CS_HREDRAW, 0, 0,
c85a994a 1408 ::LoadCursor (NULL, IDC_ARROW));
7fd59977 1409 }
1410#endif
1411 return theWClass;
1412}
1413
1414//==============================================================================
18d715bd 1415//function : CreateName
1416//purpose : Create numerical name for new object in theMap
1417//==============================================================================
1418template <typename ObjectType>
1419TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1420 const TCollection_AsciiString& theDefaultString)
1421{
1422 if (theObjectMap.IsEmpty())
1423 return theDefaultString + TCollection_AsciiString(1);
1424
1425 Standard_Integer aNextKey = 1;
1426 Standard_Boolean isFound = Standard_False;
1427 while (!isFound)
1428 {
1429 TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1430 // Look for objects with default names
1431 if (theObjectMap.IsBound1(aStringKey))
1432 {
1433 aNextKey++;
1434 }
1435 else
1436 isFound = Standard_True;
1437 }
1438
1439 return theDefaultString + TCollection_AsciiString(aNextKey);
1440}
1441
1442//==============================================================================
1443//structure : ViewerTest_Names
1444//purpose : Allow to operate with full view name: driverName/viewerName/viewName
1445//==============================================================================
1446struct ViewerTest_Names
1447{
1448private:
1449 TCollection_AsciiString myDriverName;
1450 TCollection_AsciiString myViewerName;
1451 TCollection_AsciiString myViewName;
1452
1453public:
1454
1455 const TCollection_AsciiString& GetDriverName () const
1456 {
1457 return myDriverName;
1458 }
1459 void SetDriverName (const TCollection_AsciiString& theDriverName)
1460 {
1461 myDriverName = theDriverName;
1462 }
1463 const TCollection_AsciiString& GetViewerName () const
1464 {
1465 return myViewerName;
1466 }
1467 void SetViewerName (const TCollection_AsciiString& theViewerName)
1468 {
1469 myViewerName = theViewerName;
1470 }
1471 const TCollection_AsciiString& GetViewName () const
1472 {
1473 return myViewName;
1474 }
1475 void SetViewName (const TCollection_AsciiString& theViewName)
1476 {
1477 myViewName = theViewName;
1478 }
1479
1480 //===========================================================================
1481 //function : Constructor for ViewerTest_Names
1482 //purpose : Get view, viewer, driver names from custom string
1483 //===========================================================================
1484
1485 ViewerTest_Names (const TCollection_AsciiString& theInputString)
1486 {
1487 TCollection_AsciiString aName(theInputString);
1488 if (theInputString.IsEmpty())
1489 {
1490 // Get current configuration
1491 if (ViewerTest_myDrivers.IsEmpty())
1492 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1493 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1494 else
1495 myDriverName = ViewerTest_myDrivers.Find2
1496 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1497
1498 if(ViewerTest_myContexts.IsEmpty())
1499 {
1500 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1501 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1502 }
1503 else
c48e2889 1504 {
18d715bd 1505 myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
c48e2889 1506 }
18d715bd 1507
c48e2889 1508 myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
18d715bd 1509 }
1510 else
1511 {
1512 // There is at least view name
1513 Standard_Integer aParserNumber = 0;
1514 for (Standard_Integer i = 0; i < 3; ++i)
1515 {
1516 Standard_Integer aParserPos = aName.SearchFromEnd("/");
1517 if(aParserPos != -1)
1518 {
1519 aParserNumber++;
1520 aName.Split(aParserPos-1);
1521 }
1522 else
1523 break;
1524 }
1525 if (aParserNumber == 0)
1526 {
1527 // Only view name
1528 if (!ViewerTest::GetAISContext().IsNull())
1529 {
1530 myDriverName = ViewerTest_myDrivers.Find2
1531 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1532 myViewerName = ViewerTest_myContexts.Find2
1533 (ViewerTest::GetAISContext());
1534 }
1535 else
1536 {
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"));
1540
1541 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1542 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1543 }
1544 myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1545 }
1546 else if (aParserNumber == 1)
1547 {
1548 // Here is viewerName/viewName
1549 if (!ViewerTest::GetAISContext().IsNull())
1550 myDriverName = ViewerTest_myDrivers.Find2
1551 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1552 else
1553 {
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"));
1557 }
1558 myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1559
1560 myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1561 }
1562 else
1563 {
1564 //Here is driverName/viewerName/viewName
1565 myDriverName = TCollection_AsciiString(aName);
1566
1567 TCollection_AsciiString aViewerName(theInputString);
1568 aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1569 myViewerName = TCollection_AsciiString(aViewerName);
1570
1571 myViewName = TCollection_AsciiString(theInputString);
1572 }
1573 }
1574 }
1575};
1576
1577//==============================================================================
1578//function : FindContextByView
1579//purpose : Find AIS_InteractiveContext by View
1580//==============================================================================
1581
1582Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1583{
1584 Handle(AIS_InteractiveContext) anAISContext;
1585
1586 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1587 anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1588 {
1589 if (anIter.Value()->CurrentViewer() == theView->Viewer())
1590 return anIter.Key2();
1591 }
1592 return anAISContext;
1593}
1594
18d715bd 1595//==============================================================================
1596//function : IsWindowOverlapped
1597//purpose : Check if theWindow overlapp another view
1598//==============================================================================
1599
1600Standard_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)
1605{
1606 for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1607 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1608 {
1609 Standard_Integer aTop = 0,
1610 aLeft = 0,
1611 aRight = 0,
1612 aBottom = 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))
1618 {
1619 theViewId = anIter.Key1();
1620 return Standard_True;
1621 }
1622 }
1623 return Standard_False;
1624}
1625
1626// Workaround: to create and delete non-orthographic views outside ViewerTest
1627void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1628{
1629 ViewerTest_myViews.UnBind1 (theName);
1630}
1631
1632void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1633 const Handle(V3d_View)& theView)
1634{
1635 ViewerTest_myViews.Bind (theName, theView);
1636}
1637
1638TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1639{
1640 return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1641}
8693dfd0 1642
1643//! Auxiliary tool performing continuous redraws of specified window.
1644class ViewerTest_ContinuousRedrawer
1645{
1646public:
1647 //! Return global instance.
1648 static ViewerTest_ContinuousRedrawer& Instance()
1649 {
1650 static ViewerTest_ContinuousRedrawer aRedrawer;
1651 return aRedrawer;
1652 }
1653public:
1654
1655 //! Destructor.
1656 ~ViewerTest_ContinuousRedrawer()
1657 {
1658 Stop();
1659 }
1660
1661 //! Start thread.
1662 void Start (const Handle(Aspect_Window)& theWindow,
1663 Standard_Real theTargetFps)
1664 {
1665 if (myWindow != theWindow
1666 || myTargetFps != theTargetFps)
1667 {
1668 Stop();
1669 myWindow = theWindow;
1670 myTargetFps = theTargetFps;
1671 }
1672 if (myThread.GetId() == 0)
1673 {
1674 myToStop = false;
1675 myThread.Run (this);
1676 }
1677 }
1678
1679 //! Stop thread.
1680 void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1681 {
1682 if (!theWindow.IsNull()
1683 && myWindow != theWindow)
1684 {
1685 return;
1686 }
1687
1688 {
1689 Standard_Mutex::Sentry aLock (myMutex);
1690 myToStop = true;
1691 }
1692 myThread.Wait();
1693 myToStop = false;
1694 myWindow.Nullify();
1695 }
1696
1697private:
1698
1699 //! Thread loop.
1700 void doThreadLoop()
1701 {
1702 Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1703 OSD_Timer aTimer;
1704 aTimer.Start();
1705 Standard_Real aTimeOld = 0.0;
1706 const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1707 for (;;)
1708 {
1709 {
1710 Standard_Mutex::Sentry aLock (myMutex);
1711 if (myToStop)
1712 {
1713 return;
1714 }
1715 }
1716 if (myTargetFps > 0.0)
1717 {
1718 const Standard_Real aTimeNew = aTimer.ElapsedTime();
1719 const Standard_Real aDuration = aTimeNew - aTimeOld;
1720 if (aDuration >= aTargetDur)
1721 {
1722 myWindow->InvalidateContent (aDisp);
1723 aTimeOld = aTimeNew;
1724 }
1725 }
1726 else
1727 {
1728 myWindow->InvalidateContent (aDisp);
1729 }
1730
1731 OSD::MilliSecSleep (1);
1732 }
1733 }
1734
1735 //! Thread creation callback.
1736 static Standard_Address doThreadWrapper (Standard_Address theData)
1737 {
1738 ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1739 aThis->doThreadLoop();
1740 return 0;
1741 }
1742
1743 //! Empty constructor.
1744 ViewerTest_ContinuousRedrawer()
1745 : myThread (doThreadWrapper),
1746 myTargetFps (0.0),
1747 myToStop (false) {}
1748
1749private:
1750 Handle(Aspect_Window) myWindow;
1751 OSD_Thread myThread;
1752 Standard_Mutex myMutex;
1753 Standard_Real myTargetFps;
1754 volatile bool myToStop;
1755};
1756
18d715bd 1757//==============================================================================
7fd59977 1758//function : ViewerInit
1759//purpose : Create the window viewer and initialize all the global variable
1760//==============================================================================
1761
18d715bd 1762TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1763 const Standard_Integer thePxTop,
1764 const Standard_Integer thePxWidth,
1765 const Standard_Integer thePxHeight,
9e04ccdc 1766 const TCollection_AsciiString& theViewName,
1767 const TCollection_AsciiString& theDisplayName,
1768 const Handle(V3d_View)& theViewToClone)
7fd59977 1769{
8c3c9904 1770 // Default position and dimension of the viewer window.
4fe56619 1771 // Note that left top corner is set to be sufficiently small to have
8c3c9904 1772 // window fit in the small screens (actual for remote desktops, see #23003).
4fe56619 1773 // The position corresponds to the window's client area, thus some
8c3c9904 1774 // gap is added for window frame to be visible.
1775 Standard_Integer aPxLeft = 20;
1776 Standard_Integer aPxTop = 40;
7fd59977 1777 Standard_Integer aPxWidth = 409;
1778 Standard_Integer aPxHeight = 409;
18d715bd 1779 Standard_Boolean toCreateViewer = Standard_False;
9e04ccdc 1780 if (!theViewToClone.IsNull())
1781 {
1782 theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1783 }
18d715bd 1784
58655684 1785 Handle(OpenGl_GraphicDriver) aGraphicDriver;
18d715bd 1786 ViewerTest_Names aViewNames(theViewName);
1787 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1788 aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1789
1790 if (thePxLeft != 0)
1791 aPxLeft = thePxLeft;
1792 if (thePxTop != 0)
1793 aPxTop = thePxTop;
1794 if (thePxWidth != 0)
1795 aPxWidth = thePxWidth;
1796 if (thePxHeight != 0)
7fd59977 1797 aPxHeight = thePxHeight;
4269bd1b 1798
18d715bd 1799 // Get graphic driver (create it or get from another view)
8693dfd0 1800 const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1801 if (isNewDriver)
18d715bd 1802 {
1803 // Get connection string
58655684 1804 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
8693dfd0 1805 if (!theDisplayName.IsEmpty())
1806 {
1807 SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1808 }
18d715bd 1809 else
8693dfd0 1810 {
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));
1819 }
18d715bd 1820 #else
498ce76b 1821 (void)theDisplayName; // avoid warning on unused argument
18d715bd 1822 SetDisplayConnection (new Aspect_DisplayConnection ());
1823 #endif
14cb22a1 1824
1825 if (Draw_VirtualWindows)
1826 {
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;
1831 }
59515ca6 1832 aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
58655684 1833 aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
59515ca6 1834 aGraphicDriver->InitContext();
14cb22a1 1835
18d715bd 1836 ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1837 toCreateViewer = Standard_True;
1838 }
1839 else
1840 {
58655684 1841 aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
7fd59977 1842 }
1843
18d715bd 1844 //Dispose the window if input parameters are default
1845 if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
7fd59977 1846 {
18d715bd 1847 Standard_Integer aTop = 0,
1848 aLeft = 0,
1849 aRight = 0,
1850 aBottom = 0,
1851 aScreenWidth = 0,
1852 aScreenHeight = 0;
1853
1854 // Get screen resolution
1855#if defined(_WIN32) || defined(__WIN32__)
1856 RECT aWindowSize;
1857 GetClientRect(GetDesktopWindow(), &aWindowSize);
1858 aScreenHeight = aWindowSize.bottom;
1859 aScreenWidth = aWindowSize.right;
1860#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1861 GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1862#else
1863 Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1864 aScreenWidth = WidthOfScreen(aScreen);
1865 aScreenHeight = HeightOfScreen(aScreen);
1866#endif
1867
1868 TCollection_AsciiString anOverlappedViewId("");
773f53f1 1869
1870 while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
dc3fe572 1871 {
18d715bd 1872 ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1873
1874 if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1875 && aRight + 2*aPxWidth + 40 > aScreenWidth)
1876 {
1877 if (aBottom + aPxHeight + 40 > aScreenHeight)
1878 {
1879 aPxLeft = 20;
1880 aPxTop = 40;
1881 break;
1882 }
1883 aPxLeft = 20;
1884 aPxTop = aBottom + 40;
1885 }
1886 else
1887 aPxLeft = aRight + 20;
dc3fe572 1888 }
18d715bd 1889 }
1890
1891 // Get viewer name
1892 TCollection_AsciiString aTitle("3D View - ");
1893 aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1894
1895 // Change name of current active window
49582f9d 1896 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
18d715bd 1897 {
49582f9d 1898 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
18d715bd 1899 }
1900
1901 // Create viewer
eb4320f2 1902 Handle(V3d_Viewer) a3DViewer;
18d715bd 1903 // If it's the single view, we first look for empty context
1904 if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1905 {
1906 NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1907 anIter(ViewerTest_myContexts);
1908 if (anIter.More())
1909 ViewerTest::SetAISContext (anIter.Value());
1910 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 1911 }
1912 else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1913 {
1914 ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1915 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 1916 }
eb4320f2 1917 else if (a3DViewer.IsNull())
18d715bd 1918 {
1919 toCreateViewer = Standard_True;
6a24c6de 1920 a3DViewer = new V3d_Viewer(aGraphicDriver);
f42753ed 1921 a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1922 a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1923 ViewerTest_DefaultBackground.GradientColor2,
1924 ViewerTest_DefaultBackground.FillMethod);
18d715bd 1925 }
1926
1927 // AIS context setup
1928 if (ViewerTest::GetAISContext().IsNull() ||
1929 !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1930 {
e79a94b9 1931 Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
18d715bd 1932 ViewerTest::SetAISContext (aContext);
1933 ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1934 }
1935 else
e79a94b9 1936 {
18d715bd 1937 ViewerTest::ResetEventManager();
e79a94b9 1938 }
18d715bd 1939
1940 // Create window
e79a94b9 1941#if defined(_WIN32)
1bd04b5a 1942 VT_GetWindow() = new WNT_Window (aTitle.ToCString(), WClass(),
62e1beed 1943 Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
e79a94b9 1944 aPxLeft, aPxTop,
1945 aPxWidth, aPxHeight,
1946 Quantity_NOC_BLACK);
4fe56619 1947#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
e79a94b9 1948 VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1949 aPxLeft, aPxTop,
1950 aPxWidth, aPxHeight);
1951 ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
7fd59977 1952#else
e79a94b9 1953 VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1954 aTitle.ToCString(),
1955 aPxLeft, aPxTop,
1956 aPxWidth, aPxHeight);
7fd59977 1957#endif
18d715bd 1958 VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
7fd59977 1959
d09dda09 1960 // View setup
9e04ccdc 1961 Handle(V3d_View) aView;
1962 if (!theViewToClone.IsNull())
1963 {
2e93433e 1964 aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
9e04ccdc 1965 }
1966 else
1967 {
2e93433e 1968 aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
9e04ccdc 1969 }
1970
d09dda09 1971 aView->SetWindow (VT_GetWindow());
c3282ec1 1972 ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
4269bd1b 1973
18d715bd 1974 ViewerTest::CurrentView(aView);
1975 ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
7fd59977 1976
18d715bd 1977 // Setup for X11 or NT
1978 OSWindowSetup();
7fd59977 1979
18d715bd 1980 // Set parameters for V3d_View and V3d_Viewer
1981 const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1982 aV3dView->SetComputedMode(Standard_False);
7fd59977 1983
18d715bd 1984 a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1985 if (toCreateViewer)
1986 {
7fd59977 1987 a3DViewer->SetDefaultLights();
1988 a3DViewer->SetLightOn();
18d715bd 1989 }
7fd59977 1990
8693dfd0 1991#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1992 if (isNewDriver)
1993 {
1994 ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1995 Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1996 }
1997#endif
7fd59977 1998
7fd59977 1999 VT_GetWindow()->Map();
4269bd1b 2000
18d715bd 2001 // Set the handle of created view in the event manager
2002 ViewerTest::ResetEventManager();
2003
4fe56619 2004 ViewerTest::CurrentView()->Redraw();
18d715bd 2005
2006 aView.Nullify();
2007 a3DViewer.Nullify();
18d715bd 2008
2009 return aViewNames.GetViewName();
2010}
2011
2012//==============================================================================
4269bd1b 2013//function : RedrawAllViews
2014//purpose : Redraw all created views
2015//==============================================================================
2016void ViewerTest::RedrawAllViews()
2017{
2018 NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2019 for (; aViewIt.More(); aViewIt.Next())
2020 {
2021 const Handle(V3d_View)& aView = aViewIt.Key2();
2022 aView->Redraw();
2023 }
2024}
2025
2026//==============================================================================
7fd59977 2027//function : Vinit
2028//purpose : Create the window viewer and initialize all the global variable
e79a94b9 2029// Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
7fd59977 2030//==============================================================================
2031
18d715bd 2032static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7fd59977 2033{
e79a94b9 2034 TCollection_AsciiString aViewName, aDisplayName;
2035 Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
9e04ccdc 2036 Handle(V3d_View) aCopyFrom;
e79a94b9 2037 TCollection_AsciiString aName, aValue;
2e93433e 2038 int is2dMode = -1;
e79a94b9 2039 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
18d715bd 2040 {
e79a94b9 2041 const TCollection_AsciiString anArg = theArgVec[anArgIt];
2042 TCollection_AsciiString anArgCase = anArg;
fd3f6bd0 2043 anArgCase.LowerCase();
2044 if (anArgIt + 1 < theArgsNb
2045 && anArgCase == "-name")
2046 {
2047 aViewName = theArgVec[++anArgIt];
2048 }
2049 else if (anArgIt + 1 < theArgsNb
2050 && (anArgCase == "-left"
2051 || anArgCase == "-l"))
2052 {
2053 aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2054 }
2055 else if (anArgIt + 1 < theArgsNb
2056 && (anArgCase == "-top"
2057 || anArgCase == "-t"))
2058 {
2059 aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2060 }
2061 else if (anArgIt + 1 < theArgsNb
2062 && (anArgCase == "-width"
2063 || anArgCase == "-w"))
2064 {
2065 aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2066 }
2067 else if (anArgIt + 1 < theArgsNb
2068 && (anArgCase == "-height"
2069 || anArgCase == "-h"))
18d715bd 2070 {
fd3f6bd0 2071 aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2072 }
2073 else if (anArgCase == "-exitonclose")
2074 {
49582f9d 2075 ViewerTest_EventManager::ToExitOnCloseView() = true;
fd3f6bd0 2076 if (anArgIt + 1 < theArgsNb
49582f9d 2077 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
fd3f6bd0 2078 {
2079 ++anArgIt;
2080 }
2081 }
2082 else if (anArgCase == "-closeonescape"
2083 || anArgCase == "-closeonesc")
2084 {
49582f9d 2085 ViewerTest_EventManager::ToCloseViewOnEscape() = true;
fd3f6bd0 2086 if (anArgIt + 1 < theArgsNb
49582f9d 2087 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
fd3f6bd0 2088 {
2089 ++anArgIt;
2090 }
2091 }
2e93433e 2092 else if (anArgCase == "-2d_mode"
2093 || anArgCase == "-2dmode"
2094 || anArgCase == "-2d")
2095 {
2096 bool toEnable = true;
2097 if (anArgIt + 1 < theArgsNb
2098 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2099 {
2100 ++anArgIt;
2101 }
2102 is2dMode = toEnable ? 1 : 0;
2103 }
fd3f6bd0 2104 else if (anArgIt + 1 < theArgsNb
2105 && (anArgCase == "-disp"
2106 || anArgCase == "-display"))
2107 {
2108 aDisplayName = theArgVec[++anArgIt];
2109 }
9e04ccdc 2110 else if (!ViewerTest::CurrentView().IsNull()
2111 && aCopyFrom.IsNull()
2112 && (anArgCase == "-copy"
2113 || anArgCase == "-clone"
2114 || anArgCase == "-cloneactive"
2115 || anArgCase == "-cloneactiveview"))
2116 {
2117 aCopyFrom = ViewerTest::CurrentView();
2118 }
fd3f6bd0 2119 // old syntax
2120 else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2121 {
2122 aName.LowerCase();
2123 if (aName == "name")
18d715bd 2124 {
2125 aViewName = aValue;
2126 }
fd3f6bd0 2127 else if (aName == "l"
2128 || aName == "left")
e79a94b9 2129 {
18d715bd 2130 aPxLeft = aValue.IntegerValue();
e79a94b9 2131 }
fd3f6bd0 2132 else if (aName == "t"
2133 || aName == "top")
e79a94b9 2134 {
18d715bd 2135 aPxTop = aValue.IntegerValue();
e79a94b9 2136 }
fd3f6bd0 2137 else if (aName == "disp"
2138 || aName == "display")
e79a94b9 2139 {
18d715bd 2140 aDisplayName = aValue;
e79a94b9 2141 }
fd3f6bd0 2142 else if (aName == "w"
2143 || aName == "width")
e79a94b9 2144 {
18d715bd 2145 aPxWidth = aValue.IntegerValue();
e79a94b9 2146 }
fd3f6bd0 2147 else if (aName == "h"
2148 || aName == "height")
e79a94b9 2149 {
18d715bd 2150 aPxHeight = aValue.IntegerValue();
e79a94b9 2151 }
18d715bd 2152 else
2153 {
fd3f6bd0 2154 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2155 return 1;
18d715bd 2156 }
2157 }
e79a94b9 2158 else if (aViewName.IsEmpty())
2159 {
2160 aViewName = anArg;
2161 }
2162 else
2163 {
fd3f6bd0 2164 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2165 return 1;
e79a94b9 2166 }
18d715bd 2167 }
2168
fd3f6bd0 2169#if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2170 if (!aDisplayName.IsEmpty())
2171 {
2172 aDisplayName.Clear();
2173 std::cout << "Warning: display parameter will be ignored.\n";
2174 }
2175#endif
2176
18d715bd 2177 ViewerTest_Names aViewNames (aViewName);
e79a94b9 2178 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
18d715bd 2179 {
e79a94b9 2180 TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2181 theDi.Eval (aCommand.ToCString());
2e93433e 2182 if (is2dMode != -1)
2183 {
2184 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2185 }
18d715bd 2186 return 0;
2187 }
2188
2189 TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
9e04ccdc 2190 aViewName, aDisplayName, aCopyFrom);
2e93433e 2191 if (is2dMode != -1)
2192 {
2193 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2194 }
e79a94b9 2195 theDi << aViewId;
7fd59977 2196 return 0;
2197}
2198
1eeef710 2199//! Parse HLR algo type.
2200static Standard_Boolean parseHlrAlgoType (const char* theName,
2201 Prs3d_TypeOfHLR& theType)
2202{
2203 TCollection_AsciiString aName (theName);
2204 aName.LowerCase();
2205 if (aName == "polyalgo")
2206 {
2207 theType = Prs3d_TOH_PolyAlgo;
2208 }
2209 else if (aName == "algo")
2210 {
2211 theType = Prs3d_TOH_Algo;
2212 }
2213 else
2214 {
2215 return Standard_False;
2216 }
2217 return Standard_True;
2218}
2219
7fd59977 2220//==============================================================================
0a768f56 2221//function : VHLR
2222//purpose : hidden lines removal algorithm
2223//==============================================================================
2224
2225static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2226{
1eeef710 2227 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2228 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2229 if (aView.IsNull())
0a768f56 2230 {
1eeef710 2231 std::cerr << "Error: No opened viewer!\n";
0a768f56 2232 return 1;
2233 }
2234
1eeef710 2235 Standard_Boolean hasHlrOnArg = Standard_False;
2236 Standard_Boolean hasShowHiddenArg = Standard_False;
2237 Standard_Boolean isHLROn = Standard_False;
2238 Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2239 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2240 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2241 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 2242 {
1eeef710 2243 TCollection_AsciiString anArg (argv[anArgIter]);
2244 anArg.LowerCase();
2245 if (anUpdateTool.parseRedrawMode (anArg))
2246 {
2247 continue;
2248 }
2249 else if (anArg == "-showhidden"
2250 && anArgIter + 1 < argc
2251 && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2252 {
2253 ++anArgIter;
2254 hasShowHiddenArg = Standard_True;
2255 continue;
2256 }
2257 else if ((anArg == "-type"
2258 || anArg == "-algo"
2259 || anArg == "-algotype")
2260 && anArgIter + 1 < argc
2261 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2262 {
2263 ++anArgIter;
2264 continue;
2265 }
2266 else if (!hasHlrOnArg
2267 && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2268 {
2269 hasHlrOnArg = Standard_True;
2270 continue;
2271 }
2272 // old syntax
2273 else if (!hasShowHiddenArg
2274 && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2275 {
2276 hasShowHiddenArg = Standard_True;
2277 continue;
2278 }
2279 else
2280 {
2281 std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2282 return 1;
2283 }
0a768f56 2284 }
1eeef710 2285 if (!hasHlrOnArg)
0a768f56 2286 {
1eeef710 2287 di << "HLR: " << aView->ComputedMode() << "\n";
2288 di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2289 di << "HlrAlgo: ";
2290 switch (aCtx->DefaultDrawer()->TypeOfHLR())
2291 {
2292 case Prs3d_TOH_NotSet: di << "NotSet\n"; break;
2293 case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2294 case Prs3d_TOH_Algo: di << "Algo\n"; break;
2295 }
2296 anUpdateTool.Invalidate();
2297 return 0;
0a768f56 2298 }
2299
1eeef710 2300 Standard_Boolean toRecompute = Standard_False;
2301 if (aTypeOfHLR != Prs3d_TOH_NotSet
2302 && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
e9224045 2303 {
1eeef710 2304 toRecompute = Standard_True;
2305 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2306 }
2307 if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2308 {
2309 toRecompute = Standard_True;
2310 if (toShowHidden)
e9224045 2311 {
1eeef710 2312 aCtx->DefaultDrawer()->EnableDrawHiddenLine();
e9224045 2313 }
2314 else
2315 {
1eeef710 2316 aCtx->DefaultDrawer()->DisableDrawHiddenLine();
e9224045 2317 }
1eeef710 2318 }
e9224045 2319
1eeef710 2320 // redisplay shapes
2321 if (aView->ComputedMode() && isHLROn && toRecompute)
2322 {
2323 AIS_ListOfInteractive aListOfShapes;
2324 aCtx->DisplayedObjects (aListOfShapes);
2325 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
e9224045 2326 {
1eeef710 2327 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
e9224045 2328 {
1eeef710 2329 aCtx->Redisplay (aShape, Standard_False);
e9224045 2330 }
2331 }
2332 }
0a768f56 2333
1eeef710 2334 aView->SetComputedMode (isHLROn);
0a768f56 2335 return 0;
2336}
2337
2338//==============================================================================
2339//function : VHLRType
2340//purpose : change type of using HLR algorithm
2341//==============================================================================
2342
1eeef710 2343static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
0a768f56 2344{
1eeef710 2345 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2346 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2347 if (aView.IsNull())
0a768f56 2348 {
1eeef710 2349 std::cerr << "Error: No opened viewer!\n";
0a768f56 2350 return 1;
2351 }
2352
1eeef710 2353 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2354 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2355 AIS_ListOfInteractive aListOfShapes;
2356 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 2357 {
1eeef710 2358 TCollection_AsciiString anArg (argv[anArgIter]);
2359 anArg.LowerCase();
2360 if (anUpdateTool.parseRedrawMode (anArg))
0a768f56 2361 {
1eeef710 2362 continue;
0a768f56 2363 }
1eeef710 2364 else if ((anArg == "-type"
2365 || anArg == "-algo"
2366 || anArg == "-algotype")
2367 && anArgIter + 1 < argc
2368 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2369 {
2370 ++anArgIter;
2371 continue;
2372 }
2373 // old syntax
2374 else if (aTypeOfHLR == Prs3d_TOH_NotSet
2375 && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2376 {
2377 continue;
2378 }
2379 else
0a768f56 2380 {
2381 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1eeef710 2382 TCollection_AsciiString aName (argv[anArgIter]);
0a768f56 2383 if (!aMap.IsBound2 (aName))
2384 {
1eeef710 2385 std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2386 return 1;
0a768f56 2387 }
1eeef710 2388
2389 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2390 if (aShape.IsNull())
2391 {
2392 std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2393 return 1;
2394 }
2395 aListOfShapes.Append (aShape);
2396 continue;
0a768f56 2397 }
1eeef710 2398 }
2399 if (aTypeOfHLR == Prs3d_TOH_NotSet)
2400 {
2401 std::cout << "Syntax error: wrong number of arguments!\n";
2402 return 1;
2403 }
2404
2405 const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2406 if (isGlobal)
2407 {
2408 aCtx->DisplayedObjects (aListOfShapes);
2409 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
0a768f56 2410 }
2411
1eeef710 2412 for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2413 {
2414 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2415 if (aShape.IsNull())
2416 {
2417 continue;
2418 }
2419
2420 const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2421 && aView->ComputedMode();
2422 if (!isGlobal
2423 || aShape->TypeOfHLR() != aTypeOfHLR)
2424 {
2425 aShape->SetTypeOfHLR (aTypeOfHLR);
2426 }
2427 if (toUpdateShape)
2428 {
2429 aCtx->Redisplay (aShape, Standard_False);
2430 }
2431 }
0a768f56 2432 return 0;
2433}
2434
2435//==============================================================================
18d715bd 2436//function : FindViewIdByWindowHandle
2437//purpose : Find theView Id in the map of views by window handle
2438//==============================================================================
49582f9d 2439#if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2440TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
18d715bd 2441{
2442 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2443 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2444 {
49582f9d 2445 Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
18d715bd 2446 if (aWindowHandle == theWindowHandle)
2447 return anIter.Key1();
2448 }
2449 return TCollection_AsciiString("");
2450}
2451#endif
2452
e084dbbc 2453//! Make the view active
2454void ActivateView (const TCollection_AsciiString& theViewName,
2455 Standard_Boolean theToUpdate = Standard_True)
18d715bd 2456{
2457 const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
e084dbbc 2458 if (aView.IsNull())
18d715bd 2459 {
e084dbbc 2460 return;
2461 }
18d715bd 2462
e084dbbc 2463 Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2464 if (!anAISContext.IsNull())
2465 {
49582f9d 2466 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
e084dbbc 2467 {
49582f9d 2468 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
e084dbbc 2469 }
2470
2471 ViewerTest::CurrentView (aView);
2472 ViewerTest::SetAISContext (anAISContext);
49582f9d 2473 aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
1eeef710 2474#if defined(_WIN32)
e084dbbc 2475 VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2476#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
e084dbbc 2477 VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2478#else
e084dbbc 2479 VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2480#endif
e084dbbc 2481 SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2482 if (theToUpdate)
2483 {
18d715bd 2484 ViewerTest::CurrentView()->Redraw();
2485 }
2486 }
2487}
2488
2489//==============================================================================
2490//function : RemoveView
0e93d9e5 2491//purpose :
2492//==============================================================================
2493void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2494 const Standard_Boolean theToRemoveContext)
2495{
2496 if (!ViewerTest_myViews.IsBound2 (theView))
2497 {
2498 return;
2499 }
2500
2501 const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2502 RemoveView (aViewName, theToRemoveContext);
2503}
2504
2505//==============================================================================
2506//function : RemoveView
18d715bd 2507//purpose : Close and remove view from display, clear maps if neccessary
2508//==============================================================================
2509void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2510{
2511 if (!ViewerTest_myViews.IsBound1(theViewName))
2512 {
04232180 2513 std::cout << "Wrong view name\n";
18d715bd 2514 return;
2515 }
2516
2517 // Activate another view if it's active now
2518 if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2519 {
2520 if (ViewerTest_myViews.Extent() > 1)
2521 {
2522 TCollection_AsciiString aNewViewName;
c48e2889 2523 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2524 anIter.More(); anIter.Next())
2525 {
18d715bd 2526 if (anIter.Key1() != theViewName)
2527 {
2528 aNewViewName = anIter.Key1();
2529 break;
2530 }
c48e2889 2531 }
2532 ActivateView (aNewViewName);
18d715bd 2533 }
2534 else
2535 {
e084dbbc 2536 VT_GetWindow().Nullify();
2537 ViewerTest::CurrentView (Handle(V3d_View)());
18d715bd 2538 if (isContextRemoved)
2539 {
2540 Handle(AIS_InteractiveContext) anEmptyContext;
2541 ViewerTest::SetAISContext(anEmptyContext);
2542 }
2543 }
2544 }
2545
2546 // Delete view
2547 Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2548 Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
8693dfd0 2549 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2550 aRedrawer.Stop (aView->Window());
18d715bd 2551
2552 // Remove view resources
18d715bd 2553 ViewerTest_myViews.UnBind1(theViewName);
851dacdb 2554 aView->Window()->Unmap();
18d715bd 2555 aView->Remove();
2556
2557#if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2558 XFlush (GetDisplayConnection()->GetDisplay());
2559#endif
2560
2561 // Keep context opened only if the closed view is last to avoid
2562 // unused empty contexts
2563 if (!aCurrentContext.IsNull())
2564 {
2565 // Check if there are more difined views in the viewer
f7fc0c03 2566 if ((isContextRemoved || ViewerTest_myContexts.Size() != 1)
2567 && aCurrentContext->CurrentViewer()->DefinedViews().IsEmpty())
18d715bd 2568 {
2569 // Remove driver if there is no viewers that use it
2570 Standard_Boolean isRemoveDriver = Standard_True;
2571 for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2572 anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2573 {
2574 if (aCurrentContext != anIter.Key2() &&
2575 aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2576 {
2577 isRemoveDriver = Standard_False;
2578 break;
2579 }
2580 }
2ec85268 2581
2582 aCurrentContext->RemoveAll (Standard_False);
18d715bd 2583 if(isRemoveDriver)
2584 {
2585 ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2586 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
8693dfd0 2587 Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
18d715bd 2588 #endif
2589 }
2590
2591 ViewerTest_myContexts.UnBind2(aCurrentContext);
2592 }
2593 }
04232180 2594 std::cout << "3D View - " << theViewName << " was deleted.\n";
49582f9d 2595 if (ViewerTest_EventManager::ToExitOnCloseView())
fd3f6bd0 2596 {
2597 Draw_Interprete ("exit");
2598 }
18d715bd 2599}
2600
2601//==============================================================================
2602//function : VClose
2603//purpose : Remove the view defined by its name
2604//==============================================================================
2605
d0cc1cb7 2606static int VClose (Draw_Interpretor& /*theDi*/,
2607 Standard_Integer theArgsNb,
2608 const char** theArgVec)
18d715bd 2609{
18d715bd 2610 NCollection_List<TCollection_AsciiString> aViewList;
d0cc1cb7 2611 if (theArgsNb > 1)
18d715bd 2612 {
d0cc1cb7 2613 TCollection_AsciiString anArg (theArgVec[1]);
2614 anArg.UpperCase();
2615 if (anArg.IsEqual ("ALL")
2616 || anArg.IsEqual ("*"))
2617 {
2618 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2619 anIter.More(); anIter.Next())
2620 {
2621 aViewList.Append (anIter.Key1());
2622 }
2623 if (aViewList.IsEmpty())
2624 {
2625 std::cout << "No view to close\n";
2626 return 0;
2627 }
2628 }
2629 else
18d715bd 2630 {
d0cc1cb7 2631 ViewerTest_Names aViewName (theArgVec[1]);
2632 if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2633 {
2634 std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2635 return 1;
2636 }
2637 aViewList.Append (aViewName.GetViewName());
18d715bd 2638 }
2639 }
2640 else
2641 {
d0cc1cb7 2642 // close active view
2643 if (ViewerTest::CurrentView().IsNull())
2644 {
2645 std::cerr << "No active view!\n";
2646 return 1;
2647 }
2648 aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
18d715bd 2649 }
2650
d0cc1cb7 2651 Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
18d715bd 2652 for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2653 anIter.More(); anIter.Next())
2654 {
d0cc1cb7 2655 ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
18d715bd 2656 }
2657
2658 return 0;
2659}
2660
2661//==============================================================================
2662//function : VActivate
2663//purpose : Activate the view defined by its ID
2664//==============================================================================
2665
2666static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2667{
e084dbbc 2668 if (theArgsNb == 1)
18d715bd 2669 {
2670 theDi.Eval("vviewlist");
2671 return 0;
2672 }
2673
e084dbbc 2674 TCollection_AsciiString aNameString;
2675 Standard_Boolean toUpdate = Standard_True;
2676 Standard_Boolean toActivate = Standard_True;
2677 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
18d715bd 2678 {
e084dbbc 2679 TCollection_AsciiString anArg (theArgVec[anArgIter]);
2680 anArg.LowerCase();
2681 if (toUpdate
2682 && anArg == "-noupdate")
2683 {
2684 toUpdate = Standard_False;
2685 }
2686 else if (toActivate
2687 && aNameString.IsEmpty()
2688 && anArg == "none")
2689 {
49582f9d 2690 ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
e084dbbc 2691 VT_GetWindow().Nullify();
2692 ViewerTest::CurrentView (Handle(V3d_View)());
2693 ViewerTest::ResetEventManager();
2694 theDi << theArgVec[0] << ": all views are inactive\n";
2695 toActivate = Standard_False;
2696 }
2697 else if (toActivate
2698 && aNameString.IsEmpty())
2699 {
2700 aNameString = theArgVec[anArgIter];
2701 }
2702 else
2703 {
2704 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2705 return 1;
2706 }
18d715bd 2707 }
2708
e084dbbc 2709 if (!toActivate)
2710 {
2711 return 0;
2712 }
2713 else if (aNameString.IsEmpty())
2714 {
2715 std::cout << "Syntax error: wrong number of arguments\n";
2716 return 1;
2717 }
18d715bd 2718
2719 // Check if this view exists in the viewer with the driver
e084dbbc 2720 ViewerTest_Names aViewNames (aNameString);
18d715bd 2721 if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2722 {
e084dbbc 2723 theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
18d715bd 2724 return 1;
2725 }
2726
2727 // Check if it is active already
2728 if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2729 {
2730 theDi << theArgVec[0] << ": the view is active already\n";
2731 return 0;
2732 }
2733
e084dbbc 2734 ActivateView (aViewNames.GetViewName(), toUpdate);
18d715bd 2735 return 0;
2736}
2737
2738//==============================================================================
2739//function : VViewList
2740//purpose : Print current list of views per viewer and graphic driver ID
2741// shared between viewers
2742//==============================================================================
2743
2744static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2745{
2746 if (theArgsNb > 2)
2747 {
2748 theDi << theArgVec[0] << ": Wrong number of command arguments\n"
29cb310a 2749 << "Usage: " << theArgVec[0] << " name";
18d715bd 2750 return 1;
2751 }
2752 if (ViewerTest_myContexts.Size() < 1)
2753 return 0;
2754
18d715bd 2755 Standard_Boolean isTreeView =
29cb310a 2756 (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
18d715bd 2757
2758 if (isTreeView)
c48e2889 2759 {
18d715bd 2760 theDi << theArgVec[0] <<":\n";
c48e2889 2761 }
18d715bd 2762
c48e2889 2763 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2764 aDriverIter.More(); aDriverIter.Next())
2765 {
2766 if (isTreeView)
2767 theDi << aDriverIter.Key1() << ":\n";
18d715bd 2768
c48e2889 2769 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2770 aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2771 {
2772 if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
18d715bd 2773 {
c48e2889 2774 if (isTreeView)
18d715bd 2775 {
c48e2889 2776 TCollection_AsciiString aContextName(aContextIter.Key1());
2777 theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2778 }
18d715bd 2779
c48e2889 2780 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2781 aViewIter.More(); aViewIter.Next())
2782 {
2783 if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
18d715bd 2784 {
c48e2889 2785 TCollection_AsciiString aViewName(aViewIter.Key1());
2786 if (isTreeView)
18d715bd 2787 {
c48e2889 2788 if (aViewIter.Value() == ViewerTest::CurrentView())
2789 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
18d715bd 2790 else
c48e2889 2791 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2792 }
2793 else
2794 {
2795 theDi << aViewName << " ";
18d715bd 2796 }
2797 }
2798 }
2799 }
2800 }
c48e2889 2801 }
18d715bd 2802 return 0;
2803}
2804
2805//==============================================================================
49582f9d 2806//function : GetMousePosition
2807//purpose :
7fd59977 2808//==============================================================================
49582f9d 2809void ViewerTest::GetMousePosition (Standard_Integer& theX,
2810 Standard_Integer& theY)
7fd59977 2811{
49582f9d 2812 if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
4fe56619 2813 {
49582f9d 2814 theX = aViewCtrl->LastMousePosition().x();
2815 theY = aViewCtrl->LastMousePosition().y();
4fe56619 2816 }
7fd59977 2817}
2818
2819//==============================================================================
fc552d84 2820//function : VViewProj
2821//purpose : Switch view projection
44b8f2d6 2822//==============================================================================
fc552d84 2823static int VViewProj (Draw_Interpretor& ,
2824 Standard_Integer theNbArgs,
2825 const char** theArgVec)
44b8f2d6 2826{
fc552d84 2827 static Standard_Boolean isYup = Standard_False;
2828 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2829 if (aView.IsNull())
44b8f2d6 2830 {
fc552d84 2831 std::cout << "Error: no active view\n";
44b8f2d6 2832 return 1;
2833 }
2834
fc552d84 2835 TCollection_AsciiString aCmdName (theArgVec[0]);
2836 Standard_Boolean isGeneralCmd = Standard_False;
2837 if (aCmdName == "vfront")
2838 {
2839 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2840 }
2841 else if (aCmdName == "vback")
2842 {
2843 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2844 }
2845 else if (aCmdName == "vtop")
2846 {
2847 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2848 }
2849 else if (aCmdName == "vbottom")
2850 {
2851 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2852 }
2853 else if (aCmdName == "vleft")
2854 {
2855 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2856 }
2857 else if (aCmdName == "vright")
2858 {
2859 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2860 }
2861 else if (aCmdName == "vaxo")
2862 {
2863 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2864 }
2865 else
2866 {
2867 isGeneralCmd = Standard_True;
2868 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2869 {
2870 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2871 anArgCase.LowerCase();
2872 if (anArgCase == "-zup")
2873 {
2874 isYup = Standard_False;
2875 }
2876 else if (anArgCase == "-yup")
2877 {
2878 isYup = Standard_True;
2879 }
2880 else if (anArgCase == "-front"
2881 || anArgCase == "front"
2882 || anArgCase == "-f"
2883 || anArgCase == "f")
2884 {
2885 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2886 }
2887 else if (anArgCase == "-back"
2888 || anArgCase == "back"
2889 || anArgCase == "-b"
2890 || anArgCase == "b")
2891 {
2892 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2893 }
2894 else if (anArgCase == "-top"
2895 || anArgCase == "top"
2896 || anArgCase == "-t"
2897 || anArgCase == "t")
2898 {
2899 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2900 }
2901 else if (anArgCase == "-bottom"
2902 || anArgCase == "bottom"
2903 || anArgCase == "-bot"
2904 || anArgCase == "bot"
2905 || anArgCase == "-b"
2906 || anArgCase == "b")
2907 {
2908 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2909 }
2910 else if (anArgCase == "-left"
2911 || anArgCase == "left"
2912 || anArgCase == "-l"
2913 || anArgCase == "l")
2914 {
2915 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2916 }
2917 else if (anArgCase == "-right"
2918 || anArgCase == "right"
2919 || anArgCase == "-r"
2920 || anArgCase == "r")
2921 {
2922 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2923 }
2924 else if (anArgCase == "-axoleft"
2925 || anArgCase == "-leftaxo"
2926 || anArgCase == "axoleft"
2927 || anArgCase == "leftaxo")
2928 {
2929 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2930 }
2931 else if (anArgCase == "-axo"
2932 || anArgCase == "axo"
2933 || anArgCase == "-a"
2934 || anArgCase == "a"
2935 || anArgCase == "-axoright"
2936 || anArgCase == "-rightaxo"
2937 || anArgCase == "axoright"
2938 || anArgCase == "rightaxo")
2939 {
2940 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2941 }
2942 else if (anArgCase == "+x")
2943 {
2944 aView->SetProj (V3d_Xpos, isYup);
2945 }
2946 else if (anArgCase == "-x")
2947 {
2948 aView->SetProj (V3d_Xneg, isYup);
2949 }
2950 else if (anArgCase == "+y")
2951 {
2952 aView->SetProj (V3d_Ypos, isYup);
2953 }
2954 else if (anArgCase == "-y")
2955 {
2956 aView->SetProj (V3d_Yneg, isYup);
2957 }
2958 else if (anArgCase == "+z")
2959 {
2960 aView->SetProj (V3d_Zpos, isYup);
2961 }
2962 else if (anArgCase == "-z")
2963 {
2964 aView->SetProj (V3d_Zneg, isYup);
2965 }
2966 else if (anArgCase == "+x+y+z")
2967 {
2968 aView->SetProj (V3d_XposYposZpos, isYup);
2969 }
2970 else if (anArgCase == "+x+y-z")
2971 {
2972 aView->SetProj (V3d_XposYposZneg, isYup);
2973 }
2974 else if (anArgCase == "+x-y+z")
2975 {
2976 aView->SetProj (V3d_XposYnegZpos, isYup);
2977 }
2978 else if (anArgCase == "+x-y-z")
2979 {
2980 aView->SetProj (V3d_XposYnegZneg, isYup);
2981 }
2982 else if (anArgCase == "-x+y+z")
2983 {
2984 aView->SetProj (V3d_XnegYposZpos, isYup);
2985 }
2986 else if (anArgCase == "-x+y-z")
2987 {
2988 aView->SetProj (V3d_XnegYposZneg, isYup);
2989 }
2990 else if (anArgCase == "-x-y+z")
2991 {
2992 aView->SetProj (V3d_XnegYnegZpos, isYup);
2993 }
2994 else if (anArgCase == "-x-y-z")
2995 {
2996 aView->SetProj (V3d_XnegYnegZneg, isYup);
2997 }
2998 else if (anArgCase == "+x+y")
2999 {
3000 aView->SetProj (V3d_XposYpos, isYup);
3001 }
3002 else if (anArgCase == "+x-y")
3003 {
3004 aView->SetProj (V3d_XposYneg, isYup);
3005 }
3006 else if (anArgCase == "-x+y")
3007 {
3008 aView->SetProj (V3d_XnegYpos, isYup);
3009 }
3010 else if (anArgCase == "-x-y")
3011 {
3012 aView->SetProj (V3d_XnegYneg, isYup);
3013 }
3014 else if (anArgCase == "+x+z")
3015 {
3016 aView->SetProj (V3d_XposZpos, isYup);
3017 }
3018 else if (anArgCase == "+x-z")
3019 {
3020 aView->SetProj (V3d_XposZneg, isYup);
3021 }
3022 else if (anArgCase == "-x+z")
3023 {
3024 aView->SetProj (V3d_XnegZpos, isYup);
3025 }
3026 else if (anArgCase == "-x-z")
3027 {
3028 aView->SetProj (V3d_XnegZneg, isYup);
3029 }
3030 else if (anArgCase == "+y+z")
3031 {
3032 aView->SetProj (V3d_YposZpos, isYup);
3033 }
3034 else if (anArgCase == "+y-z")
3035 {
3036 aView->SetProj (V3d_YposZneg, isYup);
3037 }
3038 else if (anArgCase == "-y+z")
3039 {
3040 aView->SetProj (V3d_YnegZpos, isYup);
3041 }
3042 else if (anArgCase == "-y-z")
3043 {
3044 aView->SetProj (V3d_YnegZneg, isYup);
3045 }
3046 else if (anArgIter + 1 < theNbArgs
3047 && anArgCase == "-frame"
3048 && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3049 {
3050 TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3051 aFrameDef.LowerCase();
3052 gp_Dir aRight, anUp;
3053 if (aFrameDef.Value (2) == aFrameDef.Value (4))
3054 {
3055 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3056 return 1;
3057 }
44b8f2d6 3058
fc552d84 3059 if (aFrameDef.Value (2) == 'x')
3060 {
3061 aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3062 }
3063 else if (aFrameDef.Value (2) == 'y')
3064 {
3065 aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3066 }
3067 else if (aFrameDef.Value (2) == 'z')
3068 {
3069 aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3070 }
3071 else
3072 {
3073 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3074 return 1;
3075 }
7fd59977 3076
fc552d84 3077 if (aFrameDef.Value (4) == 'x')
3078 {
3079 anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3080 }
3081 else if (aFrameDef.Value (4) == 'y')
3082 {
3083 anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3084 }
3085 else if (aFrameDef.Value (4) == 'z')
3086 {
3087 anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3088 }
3089 else
3090 {
3091 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3092 return 1;
3093 }
44b8f2d6 3094
fc552d84 3095 const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3096 const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3097 const gp_Dir aDir = anUp.Crossed (aRight);
3098 aCamera->SetCenter (gp_Pnt (0, 0, 0));
3099 aCamera->SetDirection (aDir);
3100 aCamera->SetUp (anUp);
3101 aCamera->OrthogonalizeUp();
44b8f2d6 3102
fc552d84 3103 aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3104 aView->Update();
3105 }
3106 else
3107 {
3108 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3109 return 1;
3110 }
3111 }
3112 }
44b8f2d6 3113
fc552d84 3114 if (!isGeneralCmd
3115 && theNbArgs != 1)
3116 {
3117 std::cout << "Syntax error: wrong number of arguments\n";
3118 return 1;
3119 }
3120 return 0;
7fd59977 3121}
3122
3123//==============================================================================
3124//function : VHelp
3125//purpose : Dsiplay help on viewer Keyboead and mouse commands
3126//Draw arg : No args
3127//==============================================================================
3128
3129static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3130{
586db386 3131 di << "=========================\n";
3132 di << "F : FitAll\n";
3133 di << "T : TopView\n";
3134 di << "B : BottomView\n";
3135 di << "R : RightView\n";
3136 di << "L : LeftView\n";
3137 di << "A : AxonometricView\n";
3138 di << "D : ResetView\n";
3139
3140 di << "=========================\n";
3141 di << "S : Shading\n";
3142 di << "W : Wireframe\n";
49582f9d 3143 di << "H : HiddenLineRemoval\n";
586db386 3144 di << "U : Unset display mode\n";
3145 di << "Delete : Remove selection from viewer\n";
3146
3147 di << "=========================\n";
3148 di << "Selection mode \n";
3149 di << "0 : Shape\n";
3150 di << "1 : Vertex\n";
3151 di << "2 : Edge\n";
3152 di << "3 : Wire\n";
3153 di << "4 : Face\n";
3154 di << "5 : Shell\n";
3155 di << "6 : Solid\n";
3156 di << "7 : Compound\n";
3157
3158 di << "=========================\n";
49582f9d 3159 di << "< : Hilight next detected\n";
3160 di << "> : Hilight previous detected\n";
7fd59977 3161
3162 return 0;
3163}
3164
57c28b61 3165#ifdef _WIN32
7fd59977 3166
49582f9d 3167static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3168 UINT theMsg,
3169 WPARAM wParam,
3170 LPARAM lParam )
7fd59977 3171{
49582f9d 3172 if (ViewerTest_myViews.IsEmpty())
3173 {
3174 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3175 }
7fd59977 3176
49582f9d 3177 switch (theMsg)
3178 {
18d715bd 3179 case WM_CLOSE:
49582f9d 3180 {
3181 // Delete view from map of views
3182 ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3183 return 0;
3184 }
18d715bd 3185 case WM_ACTIVATE:
49582f9d 3186 {
3187 if (LOWORD(wParam) == WA_CLICKACTIVE
3188 || LOWORD(wParam) == WA_ACTIVE
3189 || ViewerTest::CurrentView().IsNull())
18d715bd 3190 {
3191 // Activate inactive window
49582f9d 3192 if (VT_GetWindow().IsNull()
3193 || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
625e1958 3194 {
49582f9d 3195 ActivateView (FindViewIdByWindowHandle (theWinHandle));
625e1958 3196 }
7fd59977 3197 }
7fd59977 3198 break;
49582f9d 3199 }
7fd59977 3200 default:
49582f9d 3201 {
3202 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
7fd59977 3203 }
7fd59977 3204 }
49582f9d 3205 return 0;
7fd59977 3206}
3207
49582f9d 3208static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3209 UINT theMsg,
3210 WPARAM wParam,
3211 LPARAM lParam)
7fd59977 3212{
f978241f 3213 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3214 if (aView.IsNull())
3215 {
49582f9d 3216 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
f978241f 3217 }
7fd59977 3218
49582f9d 3219 switch (theMsg)
3220 {
7fd59977 3221 case WM_PAINT:
49582f9d 3222 {
3223 PAINTSTRUCT aPaint;
3224 BeginPaint(theWinHandle, &aPaint);
3225 EndPaint (theWinHandle, &aPaint);
3226 ViewerTest::CurrentEventManager()->ProcessExpose();
7fd59977 3227 break;
49582f9d 3228 }
7fd59977 3229 case WM_SIZE:
49582f9d 3230 {
3231 ViewerTest::CurrentEventManager()->ProcessConfigure();
7fd59977 3232 break;
49582f9d 3233 }
f978241f 3234 case WM_MOVE:
3235 case WM_MOVING:
3236 case WM_SIZING:
49582f9d 3237 {
f978241f 3238 switch (aView->RenderingParams().StereoMode)
3239 {
3240 case Graphic3d_StereoMode_RowInterlaced:
3241 case Graphic3d_StereoMode_ColumnInterlaced:
3242 case Graphic3d_StereoMode_ChessBoard:
49582f9d 3243 {
3244 // track window moves to reverse stereo pair
3245 aView->MustBeResized();
3246 aView->Update();
f978241f 3247 break;
49582f9d 3248 }
f978241f 3249 default:
3250 break;
3251 }
3252 break;
49582f9d 3253 }
3254 case WM_KEYUP:
7fd59977 3255 case WM_KEYDOWN:
49582f9d 3256 {
3257 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3258 if (aVKey != Aspect_VKey_UNKNOWN)
4fe56619 3259 {
49582f9d 3260 const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3261 if (theMsg == WM_KEYDOWN)
f978241f 3262 {
49582f9d 3263 ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
f978241f 3264 }
49582f9d 3265 else
f978241f 3266 {
49582f9d 3267 ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
f978241f 3268 }
49582f9d 3269 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
7fd59977 3270 }
3271 break;
49582f9d 3272 }
7fd59977 3273 case WM_LBUTTONUP:
3274 case WM_MBUTTONUP:
3275 case WM_RBUTTONUP:
7fd59977 3276 case WM_LBUTTONDOWN:
3277 case WM_MBUTTONDOWN:
3278 case WM_RBUTTONDOWN:
49582f9d 3279 {
3280 const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3281 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3282 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3283 switch (theMsg)
7fd59977 3284 {
49582f9d 3285 case WM_LBUTTONUP:
3286 case WM_LBUTTONDOWN:
3287 aButton = Aspect_VKeyMouse_LeftButton;
3288 break;
3289 case WM_MBUTTONUP:
3290 case WM_MBUTTONDOWN:
3291 aButton = Aspect_VKeyMouse_MiddleButton;
3292 break;
3293 case WM_RBUTTONUP:
3294 case WM_RBUTTONDOWN:
3295 aButton = Aspect_VKeyMouse_RightButton;
3296 break;
7fd59977 3297 }
49582f9d 3298 if (theMsg == WM_LBUTTONDOWN
3299 || theMsg == WM_MBUTTONDOWN
3300 || theMsg == WM_RBUTTONDOWN)
f978241f 3301 {
49582f9d 3302 if (aButton == Aspect_VKeyMouse_LeftButton)
f978241f 3303 {
49582f9d 3304 TheIsAnimating = Standard_False;
f978241f 3305 }
49582f9d 3306
3307 SetFocus (theWinHandle);
3308 SetCapture(theWinHandle);
3309 ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
f978241f 3310 }
3311 else
3312 {
49582f9d 3313 ReleaseCapture();
3314 ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
f978241f 3315 }
49582f9d 3316 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
f978241f 3317 break;
3318 }
49582f9d 3319 case WM_MOUSEWHEEL:
3320 {
3321 const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3322 const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3323 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3324 Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3325 POINT aCursorPnt = { aPos.x(), aPos.y() };
3326 if (ScreenToClient (theWinHandle, &aCursorPnt))
7fd59977 3327 {
49582f9d 3328 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3329 }
7fd59977 3330
49582f9d 3331 ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3332 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3333 break;
3334 }
3335 case WM_MOUSEMOVE:
3336 {