0030942: Draw Harness, ViewerTest - command vdefaults should abort script on unknown...
[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
293211ae 419 //! the variable set of options that are allowed for the old scenario (without any option passed)
420 CommandOptionKeyVariableSet myUnnamedOptionVariableSet;
421
077a220c 422 //! the variable set of options that are allowed for setting an environment cubemap as background
423 CommandOptionKeyVariableSet myCubeMapOptionVariableSet;
424
293211ae 425 //! the variable set of options that are allowed for setting an image as a background
426 CommandOptionKeyVariableSet myImageOptionVariableSet;
427
428 //! the variable set of options that are allowed for setting a background image fill type
429 CommandOptionKeyVariableSet myImageModeOptionVariableSet;
430
431 //! the variable set of options that are allowed for setting a gradient filling for the background
432 CommandOptionKeyVariableSet myGradientOptionVariableSet;
433
434 //! the variable set of options that are allowed for setting a background gradient filling method
435 CommandOptionKeyVariableSet myGradientModeOptionVariableSet;
436
437 //! the variable set of options that are allowed for filling a background with a specific color
438 CommandOptionKeyVariableSet myColorOptionVariableSet;
439
440 //! the variable set of options that are allowed for setting a default background gradient
441 CommandOptionKeyVariableSet myDefaultGradientOptionVariableSet;
442
443 //! the variable set of options that are allowed for setting a default background color
444 CommandOptionKeyVariableSet myDefaultColorOptionVariableSet;
445
446 //! the variable set of options that are allowed for printing help
447 CommandOptionKeyVariableSet myHelpOptionVariableSet;
448
449 //! Adds options to command parser
450 void addOptionsToCommandParser()
451 {
452 myImageOptionKey = myCommandParser.AddOption ("imageFile|image|imgFile|img",
453 "filename of image used as background");
454 myImageModeOptionKey = myCommandParser.AddOption (
455 "imageMode|imgMode", "image fill type, should be one of CENTERED, TILED, STRETCH, NONE");
456 myGradientOptionKey = myCommandParser.AddOption ("gradient|grad|gr",
457 "sets background gradient starting and ending colors");
458 myGradientModeOptionKey =
459 myCommandParser.AddOption ("gradientMode|gradMode|gradMd|grMode|grMd",
460 "gradient fill method, should be one of NONE, HOR[IZONTAL], VER[TICAL], "
461 "DIAG[ONAL]1, DIAG[ONAL]2, CORNER1, CORNER2, CORNER3, CORNER4");
462 myColorOptionKey = myCommandParser.AddOption ("color|col", "background color");
463 myDefaultOptionKey = myCommandParser.AddOption ("default|def", "sets background default gradient or color");
077a220c 464
465 myCubeMapOptionKey = myCommandParser.AddOption ("cubemap|cmap|cm", "background cubemap");
466 myCubeMapOrderOptionKey = myCommandParser.AddOption ("order|o", "order of sides in one image packed cubemap");
467 myCubeMapInvertedZOptionKey = myCommandParser.AddOption (
468 "invertedz|invz|iz", "whether Z axis is inverted or not during background cubemap rendering");
293211ae 469 }
470
471 //! Creates option sets used to determine if a passed option set is valid or not
472 void createOptionSets()
473 {
474 ViewerTest_CommandOptionKeySet anUnnamedOptionSet;
475 anUnnamedOptionSet.insert (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
476 myUnnamedOptionVariableSet = CommandOptionKeyVariableSet (anUnnamedOptionSet);
477
077a220c 478 ViewerTest_CommandOptionKeySet aCubeMapOptionSet;
479 aCubeMapOptionSet.insert (myCubeMapOptionKey);
480 ViewerTest_CommandOptionKeySet aCubeMapAdditionalOptionKeySet;
481 aCubeMapAdditionalOptionKeySet.insert (myCubeMapInvertedZOptionKey);
482 aCubeMapAdditionalOptionKeySet.insert (myCubeMapOrderOptionKey);
483 myCubeMapOptionVariableSet = CommandOptionKeyVariableSet (aCubeMapOptionSet, aCubeMapAdditionalOptionKeySet);
484
293211ae 485 ViewerTest_CommandOptionKeySet anImageOptionSet;
486 anImageOptionSet.insert (myImageOptionKey);
487 ViewerTest_CommandOptionKeySet anImageModeOptionSet;
488 anImageModeOptionSet.insert (myImageModeOptionKey);
489 myImageOptionVariableSet = CommandOptionKeyVariableSet (anImageOptionSet, anImageModeOptionSet);
490 myImageModeOptionVariableSet = CommandOptionKeyVariableSet (anImageModeOptionSet);
491
492 ViewerTest_CommandOptionKeySet aGradientOptionSet;
493 aGradientOptionSet.insert (myGradientOptionKey);
494 ViewerTest_CommandOptionKeySet aGradientModeOptionSet;
495 aGradientModeOptionSet.insert (myGradientModeOptionKey);
496 myGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
497 myGradientModeOptionVariableSet = CommandOptionKeyVariableSet (aGradientModeOptionSet);
498
499 ViewerTest_CommandOptionKeySet aColorOptionSet;
500 aColorOptionSet.insert (myColorOptionKey);
501 myColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
502
503 aGradientOptionSet.insert (myDefaultOptionKey);
504 myDefaultGradientOptionVariableSet = CommandOptionKeyVariableSet (aGradientOptionSet, aGradientModeOptionSet);
505 aColorOptionSet.insert (myDefaultOptionKey);
506 myDefaultColorOptionVariableSet = CommandOptionKeyVariableSet (aColorOptionSet);
507
508 ViewerTest_CommandOptionKeySet aHelpOptionSet;
509 aHelpOptionSet.insert (ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
510 myHelpOptionVariableSet = CommandOptionKeyVariableSet (aHelpOptionSet);
511 }
512
513 //! Prepares the command parser. Adds options and creates option sets used to determine
514 //! if a passed option set is valid or not
515 void prepareCommandParser()
516 {
517 addOptionsToCommandParser();
518 createOptionSets();
519 }
520
521 //! Adds a command description to the command parser
522 //! @param theBackgroundCommand the key of the command which description is added to the command parser
523 void addCommandDescription (const BackgroundCommand theBackgroundCommand)
524 {
525 std::string aDescription;
526 bool isMainCommand = false;
527 switch (theBackgroundCommand)
528 {
529 case BackgroundCommand_Main:
530 aDescription = "Command: vbackground (changes background or some background settings)";
531 isMainCommand = true;
532 break;
533 case BackgroundCommand_Image:
534 aDescription = "Command: vsetbg (loads image as a background)";
535 break;
536 case BackgroundCommand_ImageMode:
537 aDescription = "Command: vsetbgmode (changes background fill type)";
538 break;
539 case BackgroundCommand_Gradient:
540 aDescription = "Command: vsetgradientbg (mounts gradient background)";
541 break;
542 case BackgroundCommand_GradientMode:
543 aDescription = "Command: vsetgradientbgmode (changes gradient background fill method)";
544 break;
545 case BackgroundCommand_Color:
546 aDescription = "Command: vsetcolorbg (sets color background)";
547 break;
548 case BackgroundCommand_Default:
549 aDescription = "Command: vsetdefaultbg (sets default viewer background gradient or fill color)";
550 break;
551 default:
552 return;
553 }
554 if (!isMainCommand)
555 {
556 aDescription += "\nThis command is obsolete. Use vbackground instead.";
557 }
558 myCommandParser.SetDescription (aDescription);
559 }
560
561 //! Check if a viewer is needed to be initialized
562 //! @param theBackgroundCommand the key of the command that changes the background
563 //! @return true if processing was successful, or false otherwise
564 bool checkViewerIsNeeded (const BackgroundCommand theBackgroundCommand) const
565 {
566 const bool isMain = (theBackgroundCommand == BackgroundCommand_Main);
567 const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
568 const bool aViewerIsNotNeeded =
569 (theBackgroundCommand == BackgroundCommand_Default)
570 || (myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
571 || (myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
572 || myHelpOptionVariableSet.IsInSet (aUsedOptions);
573 return !aViewerIsNotNeeded;
574 }
575
576 //! Check if a viewer is initialized
577 //! @param theBackgroundCommandName the name of the command that changes the background
578 //! @param theDrawInterpretor the interpreter of the Draw Harness application
579 //! @return true if a viewer is initialized, or false otherwise
580 static bool checkViewerIsInitialized (const char* const theBackgroundCommandName,
581 Draw_Interpretor& theDrawInterpretor)
582 {
583 const Handle (AIS_InteractiveContext)& anAISContext = ViewerTest::GetAISContext();
584 if (anAISContext.IsNull())
585 {
586 theDrawInterpretor << "Use 'vinit' command before executing '" << theBackgroundCommandName << "' command.\n";
587 return false;
588 }
589 return true;
590 }
591
592 //! Processes command options
593 //! @param theBackgroundCommandName the name of the command that changes the background
594 //! @param theBackgroundCommand the key of the command that changes the background
595 //! @param theDrawInterpretor the interpreter of the Draw Harness application
596 //! @return true if processing was successful, or false otherwise
597 bool processCommandOptions (const char* const theBackgroundCommandName,
598 const BackgroundCommand theBackgroundCommand,
599 Draw_Interpretor& theDrawInterpretor) const
600 {
601 if (myCommandParser.HasNoOption())
602 {
603 return printHelp (theBackgroundCommandName, theDrawInterpretor);
604 }
605 if (checkViewerIsNeeded (theBackgroundCommand)
606 && !checkViewerIsInitialized (theBackgroundCommandName, theDrawInterpretor))
607 {
608 return false;
609 }
610 if (myCommandParser.HasOnlyUnnamedOption())
611 {
612 return processUnnamedOption (theBackgroundCommand);
613 }
614 return processNamedOptions (theBackgroundCommandName, theBackgroundCommand, theDrawInterpretor);
615 }
616
617 //! Processes the unnamed option
618 //! @param theBackgroundCommand the key of the command that changes the background
619 //! @return true if processing was successful, or false otherwise
620 bool processUnnamedOption (const BackgroundCommand theBackgroundCommand) const
621 {
622 switch (theBackgroundCommand)
623 {
624 case BackgroundCommand_Main:
625 return false;
626 case BackgroundCommand_Image:
627 return processImageUnnamedOption();
628 case BackgroundCommand_ImageMode:
629 return processImageModeUnnamedOption();
630 case BackgroundCommand_Gradient:
631 return processGradientUnnamedOption();
632 case BackgroundCommand_GradientMode:
633 return processGradientModeUnnamedOption();
634 case BackgroundCommand_Color:
635 return processColorUnnamedOption();
636 case BackgroundCommand_Default:
637 return processDefaultUnnamedOption();
638 default:
639 return false;
640 }
641 }
642
643 //! Processes the image unnamed option
644 //! @return true if processing was successful, or false otherwise
645 bool processImageUnnamedOption() const
646 {
647 const std::size_t aNumberOfImageUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
648 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
649 if ((aNumberOfImageUnnamedOptionArguments != 1) && (aNumberOfImageUnnamedOptionArguments != 2))
650 {
651 return false;
652 }
653 std::string anImageFileName;
654 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 0, anImageFileName))
655 {
656 return false;
657 }
658 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
659 if (aNumberOfImageUnnamedOptionArguments == 2)
660 {
661 std::string anImageModeString;
662 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, 1, anImageModeString))
663 {
664 return false;
665 }
666 if (!getBackgroundImageFillMethodByName (anImageModeString.c_str(), anImageMode))
667 {
668 return false;
669 }
670 }
671 setImage (anImageFileName.c_str(), anImageMode);
672 return true;
673 }
674
675 //! Processes the image mode unnamed option
676 //! @return true if processing was successful, or false otherwise
677 bool processImageModeUnnamedOption() const
678 {
679 return processImageModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
680 }
681
682 //! Processes the gradient unnamed option
683 //! @param theSetGradient the function used to set a background gradient filling
684 //! @return true if processing was successful, or false otherwise
685 bool processGradientUnnamedOption (SetGradientFunction* const theSetGradient = setGradient) const
686 {
687 const Standard_Integer aNumberOfGradientUnnamedOptionArguments = myCommandParser.GetNumberOfOptionArguments (
688 ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
689 if (aNumberOfGradientUnnamedOptionArguments < 2)
690 {
691 return false;
692 }
693
694 Standard_Integer anArgumentIndex = 0;
695 Quantity_Color aColor1;
696 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor1))
697 {
698 return false;
699 }
700 if (anArgumentIndex >= aNumberOfGradientUnnamedOptionArguments)
701 {
702 return false;
703 }
704
705 Quantity_Color aColor2;
706 if (!myCommandParser.ArgColor (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, anArgumentIndex, aColor2))
707 {
708 return false;
709 }
710 if (anArgumentIndex > aNumberOfGradientUnnamedOptionArguments)
711 {
712 return false;
713 }
714
715 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
716 if (anArgumentIndex == aNumberOfGradientUnnamedOptionArguments - 1)
717 {
718 std::string anGradientModeString;
719
720 if (!myCommandParser.Arg (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY,
721 anArgumentIndex,
722 anGradientModeString))
723 {
724 return false;
725 }
726 if (!getBackgroundGradientFillMethodByName (anGradientModeString.c_str(), aGradientMode))
727 {
728 return false;
729 }
730 ++anArgumentIndex;
731 }
732 if (anArgumentIndex != aNumberOfGradientUnnamedOptionArguments)
733 {
734 return false;
735 }
736 theSetGradient (aColor1, aColor2, aGradientMode);
737 return true;
738 }
739
740 //! Processes the gradient mode unnamed option
741 //! @return true if processing was successful, or false otherwise
742 bool processGradientModeUnnamedOption() const
743 {
744 return processGradientModeOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY);
745 }
746
747 //! Processes the color unnamed option
748 //! @param theSetColor the function used to set a background color
749 //! @return true if processing was successful, or false otherwise
750 bool processColorUnnamedOption (SetColorFunction* const theSetColor = setColor) const
751 {
752 return processColorOptionSet (ViewerTest_CmdParser::THE_UNNAMED_COMMAND_OPTION_KEY, theSetColor);
753 }
754
755 //! Processes the default back unnamed option
756 //! @return true if processing was successful, or false otherwise
757 bool processDefaultUnnamedOption() const
758 {
759 if (processGradientUnnamedOption (setDefaultGradient))
760 {
761 return true;
762 }
763 return processColorUnnamedOption (setDefaultColor);
764 }
765
766 //! Processes named options
767 //! @param theBackgroundCommandName the name of the command that changes the background
768 //! @param theBackgroundCommand the key of the command that changes the background
769 //! @param theDrawInterpretor the interpreter of the Draw Harness application
770 //! @return true if processing was successful, or false otherwise
771 bool processNamedOptions (const char* const theBackgroundCommandName,
772 const BackgroundCommand theBackgroundCommand,
773 Draw_Interpretor& theDrawInterpretor) const
774 {
775 const bool isMain = (theBackgroundCommand == BackgroundCommand_Main);
776 const ViewerTest_CommandOptionKeySet aUsedOptions = myCommandParser.GetUsedOptions();
077a220c 777 if (myCubeMapOptionVariableSet.IsInSet (aUsedOptions) && isMain)
778 {
779 return processCubeMapOptionSet();
780 }
293211ae 781 if (myImageOptionVariableSet.IsInSet (aUsedOptions)
782 && (isMain || (theBackgroundCommand == BackgroundCommand_Image)))
783 {
784 return processImageOptionSet();
785 }
786 if (myImageModeOptionVariableSet.IsInSet (aUsedOptions)
787 && (isMain || (theBackgroundCommand == BackgroundCommand_ImageMode)))
788 {
789 return processImageModeOptionSet();
790 }
791 if (myGradientOptionVariableSet.IsInSet (aUsedOptions)
792 && (isMain || (theBackgroundCommand == BackgroundCommand_Gradient)))
793 {
794 return processGradientOptionSet();
795 }
796 if (myGradientModeOptionVariableSet.IsInSet (aUsedOptions)
797 && (isMain || (theBackgroundCommand == BackgroundCommand_GradientMode)))
798 {
799 return processGradientModeOptionSet();
800 }
801 if (myColorOptionVariableSet.IsInSet (aUsedOptions)
802 && (isMain || (theBackgroundCommand == BackgroundCommand_Color)))
803 {
804 return processColorOptionSet();
805 }
806 if ((myDefaultGradientOptionVariableSet.IsInSet (aUsedOptions) && isMain)
807 || (myGradientOptionVariableSet.IsInSet (aUsedOptions)
808 && (theBackgroundCommand == BackgroundCommand_Default)))
809 {
810 return processDefaultGradientOptionSet();
811 }
812 if ((myDefaultColorOptionVariableSet.IsInSet (aUsedOptions) && isMain)
813 || (myColorOptionVariableSet.IsInSet (aUsedOptions) && (theBackgroundCommand == BackgroundCommand_Default)))
814 {
815 return processDefaultColorOptionSet();
816 }
817 if (myHelpOptionVariableSet.IsInSet (aUsedOptions))
818 {
819 return processHelpOptionSet (theBackgroundCommandName, theDrawInterpretor);
820 }
821 return false;
822 }
823
077a220c 824 //! Process the cubemap option set in named and unnamed case.
825 //! @return true if processing was successful, or false otherwise
826 bool processCubeMapOptionSet() const
827 {
828 NCollection_Array1<TCollection_AsciiString> aFilePaths;
829
830 if (!processCubeMapOptions (aFilePaths))
831 {
832 return false;
833 }
834
835 Graphic3d_CubeMapOrder anOrder = Graphic3d_CubeMapOrder::Default();
836
837 if (myCommandParser.HasOption (myCubeMapOrderOptionKey))
838 {
839 if (!processCubeMapOrderOptions (anOrder))
840 {
841 return false;
842 }
843 }
844
845 bool aZIsInverted = false;
846 if (myCommandParser.HasOption (myCubeMapInvertedZOptionKey))
847 {
848 if (!processCubeMapInvertedZOptionSet())
849 {
850 return false;
851 }
852 aZIsInverted = true;
853 }
854
855 setCubeMap (aFilePaths, anOrder.Validated(), aZIsInverted);
856 return true;
857 }
858
293211ae 859 //! Processes the image option set
860 //! @return true if processing was successful, or false otherwise
861 bool processImageOptionSet() const
862 {
863 std::string anImageFileName;
864 if (!processImageOption (anImageFileName))
865 {
866 return false;
867 }
868 Aspect_FillMethod anImageMode = Aspect_FM_CENTERED;
869 if (myCommandParser.HasOption (myImageModeOptionKey) && !processImageModeOption (anImageMode))
870 {
871 return false;
872 }
873 setImage (anImageFileName.c_str(), anImageMode);
874 return true;
875 }
876
877 //! Processes the image mode option set
878 //! @return true if processing was successful, or false otherwise
879 bool processImageModeOptionSet() const
880 {
881 return processImageModeOptionSet (myImageModeOptionKey);
882 }
883
884 //! Processes the image mode option set
885 //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
886 //! @return true if processing was successful, or false otherwise
887 bool processImageModeOptionSet (const ViewerTest_CommandOptionKey theImageModeOptionKey) const
888 {
889 Aspect_FillMethod anImageMode = Aspect_FM_NONE;
890 if (!processImageModeOption (theImageModeOptionKey, anImageMode))
891 {
892 return false;
893 }
894 setImageMode (anImageMode);
895 return true;
896 }
897
898 //! Processes the gradient option set
899 //! @param theSetGradient the function used to set a background gradient filling
900 //! @return true if processing was successful, or false otherwise
901 bool processGradientOptionSet (SetGradientFunction* const theSetGradient = setGradient) const
902 {
903 Quantity_Color aColor1;
904 Quantity_Color aColor2;
905 if (!processGradientOption (aColor1, aColor2))
906 {
907 return false;
908 }
909 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_HOR;
910 if (myCommandParser.HasOption (myGradientModeOptionKey) && !processGradientModeOption (aGradientMode))
911 {
912 return false;
913 }
914 theSetGradient (aColor1, aColor2, aGradientMode);
915 return true;
916 }
917
918 //! Processes the gradient mode option set
919 //! @return true if processing was successful, or false otherwise
920 bool processGradientModeOptionSet() const
921 {
922 return processGradientModeOptionSet (myGradientModeOptionKey);
923 }
924
925 //! Processes the gradient mode option set
926 //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
927 //! @return true if processing was successful, or false otherwise
928 bool processGradientModeOptionSet (const ViewerTest_CommandOptionKey theGradientModeOptionKey) const
929 {
930 Aspect_GradientFillMethod aGradientMode = Aspect_GFM_NONE;
931 if (!processGradientModeOption (theGradientModeOptionKey, aGradientMode))
932 {
933 return false;
934 }
935 setGradientMode (aGradientMode);
936 return true;
937 }
938
939 //! Processes the color option set
940 //! @param theSetColor the function used to set a background color
941 //! @return true if processing was successful, or false otherwise
942 bool processColorOptionSet (SetColorFunction* const theSetColor = setColor) const
943 {
944 return processColorOptionSet (myColorOptionKey, theSetColor);
945 }
946
947 //! Processes the default color option set
948 //! @return true if processing was successful, or false otherwise
949 bool processDefaultGradientOptionSet() const
950 {
951 return processGradientOptionSet (setDefaultGradient);
952 }
953
954 //! Processes the default gradient option set
955 //! @return true if processing was successful, or false otherwise
956 bool processDefaultColorOptionSet() const
957 {
958 return processColorOptionSet (setDefaultColor);
959 }
960
961 //! Processes the color option set
962 //! @param theColorOptionKey the key of the option that is interpreted as a color option
963 //! @param theSetColor the function used to set a background color
964 //! @return true if processing was successful, or false otherwise
965 bool processColorOptionSet (const ViewerTest_CommandOptionKey theColorOptionKey,
966 SetColorFunction* const theSetColor = setColor) const
967 {
968 Quantity_Color aColor;
969 if (!processColorOption (theColorOptionKey, aColor))
970 {
971 return false;
972 }
973 theSetColor (aColor);
974 return true;
975 }
976
977 //! Processes the help option set
978 //! @param theBackgroundCommandName the name of the command that changes the background
979 //! @param theDrawInterpretor the interpreter of the Draw Harness application
980 //! @return true if processing was successful, or false otherwise
981 bool processHelpOptionSet (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor) const
982 {
983 const Standard_Integer aNumberOfHelpOptionArguments = myCommandParser.GetNumberOfOptionArguments (
984 ViewerTest_CmdParser::THE_HELP_COMMAND_OPTION_KEY);
985 if (aNumberOfHelpOptionArguments != 0)
986 {
987 return false;
988 }
989 return printHelp (theBackgroundCommandName, theDrawInterpretor);
990 }
991
077a220c 992 //! Processes the cubemap option
993 //! @param theFilePaths the array of filenames of cubemap sides
994 //! @return true if processing was successful, or false otherwise
995 bool processCubeMapOptions (NCollection_Array1<TCollection_AsciiString> &theFilePaths) const
996 {
997 const Standard_Integer aNumberOfCubeMapOptionArguments = myCommandParser.GetNumberOfOptionArguments (myCubeMapOptionKey);
998
999 if (aNumberOfCubeMapOptionArguments != 1
1000 && aNumberOfCubeMapOptionArguments != 6)
1001 {
1002 return false;
1003 }
1004
1005 theFilePaths.Resize(0, aNumberOfCubeMapOptionArguments - 1, Standard_False);
1006
1007 for (int i = 0; i < aNumberOfCubeMapOptionArguments; ++i)
1008 {
1009 std::string aCubeMapFileName;
1010 if (!myCommandParser.Arg (myCubeMapOptionKey, i, aCubeMapFileName))
1011 {
1012 return false;
1013 }
1014 theFilePaths[i] = aCubeMapFileName.c_str();
1015 }
1016
1017 return true;
1018 }
1019
1020 //! Processes the cubemap option
1021 //! @param theIsNeededToRedraw defines need of redraw after option's processing
1022 //! @return true if processing was successful, or false otherwise
1023 bool processCubeMapInvertedZOptionSet () const
1024 {
1025 const Standard_Integer aNumberOfCubeMapZInversionOptionArguments =
1026 myCommandParser.GetNumberOfOptionArguments (myCubeMapInvertedZOptionKey);
1027
1028 if (aNumberOfCubeMapZInversionOptionArguments != 0)
1029 {
1030 return false;
1031 }
1032
1033 return true;
1034 }
1035
1036 //! Processes the tiles order option
1037 //! @param theOrder the array of indexes if cubemap sides in tile grid
1038 //! @return true if processing was successful, or false otherwise
1039 bool processCubeMapOrderOptions (Graphic3d_CubeMapOrder& theOrder) const
1040 {
1041 const Standard_Integer aNumberOfCubeMapOrderOptionArguments = myCommandParser.GetNumberOfOptionArguments(
1042 myCubeMapOrderOptionKey);
1043
1044 if (aNumberOfCubeMapOrderOptionArguments != 6)
1045 {
1046 return false;
1047 }
1048
1049
1050 for (unsigned int i = 0; i < 6; ++i)
1051 {
1052 std::string anOrderItem;
1053 if (!myCommandParser.Arg (myCubeMapOrderOptionKey, i, anOrderItem))
1054 {
1055 return false;
1056 }
1057
1058 theOrder.Set (Graphic3d_CubeMapSide (i),
1059 static_cast<unsigned char> (Draw::Atoi (anOrderItem.c_str())));
1060 }
1061
1062 return theOrder.IsValid();
1063 }
1064
293211ae 1065 //! Processes the image option
1066 //! @param theImageFileName the filename of the image to be used as a background
1067 //! @return true if processing was successful, or false otherwise
1068 bool processImageOption (std::string& theImageFileName) const
1069 {
1070 const Standard_Integer aNumberOfImageOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1071 myImageOptionKey);
1072 if (aNumberOfImageOptionArguments != 1)
1073 {
1074 return false;
1075 }
1076 std::string anImageFileName;
1077 if (!myCommandParser.Arg (myImageOptionKey, 0, anImageFileName))
1078 {
1079 return false;
1080 }
1081 theImageFileName = anImageFileName;
1082 return true;
1083 }
1084
1085 //! Processes the image mode option
1086 //! @param theImageMode the fill type used for a background image
1087 //! @return true if processing was successful, or false otherwise
1088 bool processImageModeOption (Aspect_FillMethod& theImageMode) const
1089 {
1090 return processImageModeOption (myImageModeOptionKey, theImageMode);
1091 }
1092
1093 //! Processes the image mode option
1094 //! @param theImageModeOptionKey the key of the option that is interpreted as an image mode option
1095 //! @param theImageMode the fill type used for a background image
1096 //! @return true if processing was successful, or false otherwise
1097 bool processImageModeOption (const ViewerTest_CommandOptionKey theImageModeOptionKey,
1098 Aspect_FillMethod& theImageMode) const
1099 {
1100 return processModeOption (theImageModeOptionKey, getBackgroundImageFillMethodByName, theImageMode);
1101 }
1102
1103 //! Processes the gradient option
1104 //! @param theColor1 the gradient starting color
1105 //! @param theColor2 the gradient ending color
1106 //! @return true if processing was successful, or false otherwise
1107 bool processGradientOption (Quantity_Color& theColor1, Quantity_Color& theColor2) const
1108 {
1109 Standard_Integer anArgumentIndex = 0;
1110 Quantity_Color aColor1;
1111 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor1))
1112 {
1113 return false;
1114 }
1115 Quantity_Color aColor2;
1116 if (!myCommandParser.ArgColor (myGradientOptionKey, anArgumentIndex, aColor2))
1117 {
1118 return false;
1119 }
1120 const Standard_Integer aNumberOfGradientOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1121 myGradientOptionKey);
1122 if (anArgumentIndex != aNumberOfGradientOptionArguments)
1123 {
1124 return false;
1125 }
1126 theColor1 = aColor1;
1127 theColor2 = aColor2;
1128 return true;
1129 }
1130
1131 //! Processes the gradient mode option
1132 //! @param theGradientMode the fill method used for a background gradient filling
1133 //! @return true if processing was successful, or false otherwise
1134 bool processGradientModeOption (Aspect_GradientFillMethod& theGradientMode) const
1135 {
1136 return processGradientModeOption (myGradientModeOptionKey, theGradientMode);
1137 }
1138
1139 //! Processes the gradient mode option
1140 //! @param theGradientModeOptionKey the key of the option that is interpreted as a gradient mode option
1141 //! @param theGradientMode the fill method used for a background gradient filling
1142 //! @return true if processing was successful, or false otherwise
1143 bool processGradientModeOption (const ViewerTest_CommandOptionKey theGradientModeOptionKey,
1144 Aspect_GradientFillMethod& theGradientMode) const
1145 {
1146 return processModeOption (theGradientModeOptionKey, getBackgroundGradientFillMethodByName, theGradientMode);
1147 }
1148
1149 //! Processes some mode option
1150 //! @tparam TheMode the type of a mode to be processed
1151 //! @param theModeOptionKey the key of the option that is interpreted as a mode option
1152 //! @param theMode a mode to be processed
1153 //! @return true if processing was successful, or false otherwise
1154 template <typename TheMode>
1155 bool processModeOption (const ViewerTest_CommandOptionKey theModeOptionKey,
1156 bool (*const theGetModeByName) (const TCollection_AsciiString& /* theModeName */,
1157 TheMode& /* theMode */),
1158 TheMode& theMode) const
1159 {
1160 const Standard_Integer aNumberOfModeOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1161 theModeOptionKey);
1162 if (aNumberOfModeOptionArguments != 1)
1163 {
1164 return false;
1165 }
1166 std::string aModeString;
1167 if (!myCommandParser.Arg (theModeOptionKey, 0, aModeString))
1168 {
1169 return false;
1170 }
1171 TheMode aMode = TheMode();
1172 if (!theGetModeByName (aModeString.c_str(), aMode))
1173 {
1174 return false;
1175 }
1176 theMode = aMode;
1177 return true;
1178 }
1179
1180 //! Processes the color option
1181 //! @param theColor a color used for filling a background
1182 //! @return true if processing was successful, or false otherwise
1183 bool processColorOption (Quantity_Color& theColor) const
1184 {
1185 return processColorOption (myColorOptionKey, theColor);
1186 }
1187
1188 //! Processes the color option
1189 //! @param theColorOptionKey the key of the option that is interpreted as a color option
1190 //! @param theColor a color used for filling a background
1191 //! @return true if processing was successful, or false otherwise
1192 bool processColorOption (const ViewerTest_CommandOptionKey theColorOptionKey, Quantity_Color& theColor) const
1193 {
1194 Standard_Integer anArgumentIndex = 0;
1195 Quantity_Color aColor;
1196 if (!myCommandParser.ArgColor (theColorOptionKey, anArgumentIndex, aColor))
1197 {
1198 return false;
1199 }
1200 const Standard_Integer aNumberOfColorOptionArguments = myCommandParser.GetNumberOfOptionArguments (
1201 theColorOptionKey);
1202 if (anArgumentIndex != aNumberOfColorOptionArguments)
1203 {
1204 return false;
1205 }
1206 theColor = aColor;
1207 return true;
1208 }
1209
1210 //! Prints helping message
1211 //! @param theBackgroundCommandName the name of the command that changes the background
1212 //! @param theDrawInterpretor the interpreter of the Draw Harness application
1213 //! @return true if printing was successful, or false otherwise
1214 static bool printHelp (const char* const theBackgroundCommandName, Draw_Interpretor& theDrawInterpretor)
1215 {
1216 return theDrawInterpretor.PrintHelp (theBackgroundCommandName) == TCL_OK;
1217 }
1218
077a220c 1219 //! Sets the cubemap as a background
1220 //! @param theFileNames the array of filenames of packed or multifile cubemap
1221 //! @param theOrder array of cubemap sides indexes mapping them from tiles in packed cubemap
1222 static void setCubeMap (const NCollection_Array1<TCollection_AsciiString>& theFileNames,
1223 const Graphic3d_ValidatedCubeMapOrder theOrder = Graphic3d_CubeMapOrder::Default(),
1224 bool theZIsInverted = false)
1225 {
1226 const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
1227 Handle(Graphic3d_CubeMap) aCubeMap;
1228
1229 if (theFileNames.Size() == 1)
1230 aCubeMap = new Graphic3d_CubeMapPacked(theFileNames[0], theOrder);
1231 else
1232 aCubeMap = new Graphic3d_CubeMapSeparate(theFileNames);
1233
1234 aCubeMap->SetZInversion (theZIsInverted);
1235
1236 aCubeMap->GetParams()->SetFilter(Graphic3d_TOTF_BILINEAR);
1237 aCubeMap->GetParams()->SetRepeat(Standard_False);
1238 aCubeMap->GetParams()->SetTextureUnit(Graphic3d_TextureUnit_EnvMap);
1239
1240 aCurrentView->SetBackgroundCubeMap (aCubeMap, Standard_True);
1241 }
1242
293211ae 1243 //! Sets the image as a background
1244 //! @param theImageFileName the filename of the image to be used as a background
1245 //! @param theImageMode the fill type used for a background image
1246 static void setImage (const Standard_CString theImageFileName, const Aspect_FillMethod theImageMode)
1247 {
1248 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1249 aCurrentView->SetBackgroundImage (theImageFileName, theImageMode, Standard_True);
1250 }
1251
1252 //! Sets the fill type used for a background image
1253 //! @param theImageMode the fill type used for a background image
1254 static void setImageMode (const Aspect_FillMethod theImageMode)
1255 {
1256 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1257 aCurrentView->SetBgImageStyle (theImageMode, Standard_True);
1258 }
1259
1260 //! Sets the gradient filling for a background
1261 //! @param theColor1 the gradient starting color
1262 //! @param theColor2 the gradient ending color
1263 //! @param theGradientMode the fill method used for a background gradient filling
1264 static void setGradient (const Quantity_Color& theColor1,
1265 const Quantity_Color& theColor2,
1266 const Aspect_GradientFillMethod theGradientMode)
1267 {
1268 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1269 aCurrentView->SetBgGradientColors (theColor1, theColor2, theGradientMode, Standard_True);
1270 }
1271
1272 //! Sets the fill method used for a background gradient filling
1273 //! @param theGradientMode the fill method used for a background gradient filling
1274 static void setGradientMode (const Aspect_GradientFillMethod theGradientMode)
1275 {
1276 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1277 aCurrentView->SetBgGradientStyle (theGradientMode, Standard_True);
1278 }
1279
1280 //! Sets the color used for filling a background
1281 //! @param theColor the color used for filling a background
1282 static void setColor (const Quantity_Color& theColor)
1283 {
1284 const Handle (V3d_View)& aCurrentView = ViewerTest::CurrentView();
1285 aCurrentView->SetBgGradientStyle (Aspect_GFM_NONE);
1286 aCurrentView->SetBackgroundColor (theColor);
1287 aCurrentView->Update();
1288 }
1289
1290 //! Sets the gradient filling for a background in a default viewer
1291 //! @param theColor1 the gradient starting color
1292 //! @param theColor2 the gradient ending color
1293 //! @param theGradientMode the fill method used for a background gradient filling
1294 static void setDefaultGradient (const Quantity_Color& theColor1,
1295 const Quantity_Color& theColor2,
1296 const Aspect_GradientFillMethod theGradientMode)
1297 {
1298 ViewerTest_DefaultBackground.GradientColor1 = theColor1;
1299 ViewerTest_DefaultBackground.GradientColor2 = theColor2;
1300 ViewerTest_DefaultBackground.FillMethod = theGradientMode;
1301 setDefaultGradient();
1302 }
1303
1304 //! Sets the color used for filling a background in a default viewer
1305 //! @param theColor the color used for filling a background
1306 static void setDefaultColor (const Quantity_Color& theColor)
1307 {
1308 ViewerTest_DefaultBackground.GradientColor1 = Quantity_Color();
1309 ViewerTest_DefaultBackground.GradientColor2 = Quantity_Color();
1310 ViewerTest_DefaultBackground.FillMethod = Aspect_GFM_NONE;
1311 ViewerTest_DefaultBackground.FlatColor = theColor;
1312 setDefaultGradient();
1313 setDefaultColor();
1314 }
1315
1316 //! Sets the gradient filling for a background in a default viewer.
1317 //! Gradient settings are taken from ViewerTest_DefaultBackground structure
1318 static void setDefaultGradient()
1319 {
1320 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1321 anInteractiveContextIterator (ViewerTest_myContexts);
1322 anInteractiveContextIterator.More();
1323 anInteractiveContextIterator.Next())
1324 {
1325 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1326 aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1327 ViewerTest_DefaultBackground.GradientColor2,
1328 ViewerTest_DefaultBackground.FillMethod);
1329 }
1330 }
1331
1332 //! Sets the color used for filling a background in a default viewer.
1333 //! The color value is taken from ViewerTest_DefaultBackground structure
1334 static void setDefaultColor()
1335 {
1336 for (NCollection_DoubleMap<TCollection_AsciiString, Handle (AIS_InteractiveContext)>::Iterator
1337 anInteractiveContextIterator (ViewerTest_myContexts);
1338 anInteractiveContextIterator.More();
1339 anInteractiveContextIterator.Next())
1340 {
1341 const Handle (V3d_Viewer)& aViewer = anInteractiveContextIterator.Value()->CurrentViewer();
1342 aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1343 }
1344 }
1345 };
1346
1347} // namespace
b12e1c7b 1348
625e1958 1349typedef NCollection_Map<AIS_Manipulator*> ViewerTest_MapOfAISManipulators;
1350
1351Standard_EXPORT ViewerTest_MapOfAISManipulators& GetMapOfAISManipulators()
1352{
1353 static ViewerTest_MapOfAISManipulators aMap;
1354 return aMap;
1355}
1356
1357Standard_EXPORT Handle(AIS_Manipulator) GetActiveAISManipulator()
1358{
1359 ViewerTest_MapOfAISManipulators::Iterator anIt (GetMapOfAISManipulators());
1360 for (; anIt.More(); anIt.Next())
1361 {
1362 if (anIt.Value()->HasActiveMode())
1363 {
1364 return anIt.Value();
1365 }
1366 }
1367 return NULL;
1368}
1369
7fd59977 1370//==============================================================================
1371
57c28b61 1372#ifdef _WIN32
7fd59977 1373static LRESULT WINAPI ViewerWindowProc(
1374 HWND hwnd,
1375 UINT uMsg,
1376 WPARAM wParam,
1377 LPARAM lParam );
1378static LRESULT WINAPI AdvViewerWindowProc(
1379 HWND hwnd,
1380 UINT uMsg,
1381 WPARAM wParam,
1382 LPARAM lParam );
1383#endif
1384
1385
1386//==============================================================================
1387//function : WClass
1388//purpose :
1389//==============================================================================
1390
ad03c234 1391const Handle(Standard_Transient)& ViewerTest::WClass()
7fd59977 1392{
ad03c234 1393 static Handle(Standard_Transient) theWClass;
58655684 1394#if defined(_WIN32)
4fe56619 1395 if (theWClass.IsNull())
1396 {
7c65581d 1397 theWClass = new WNT_WClass ("GW3D_Class", (Standard_Address )AdvViewerWindowProc,
ad03c234 1398 CS_VREDRAW | CS_HREDRAW, 0, 0,
c85a994a 1399 ::LoadCursor (NULL, IDC_ARROW));
7fd59977 1400 }
1401#endif
1402 return theWClass;
1403}
1404
1405//==============================================================================
18d715bd 1406//function : CreateName
1407//purpose : Create numerical name for new object in theMap
1408//==============================================================================
1409template <typename ObjectType>
1410TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
1411 const TCollection_AsciiString& theDefaultString)
1412{
1413 if (theObjectMap.IsEmpty())
1414 return theDefaultString + TCollection_AsciiString(1);
1415
1416 Standard_Integer aNextKey = 1;
1417 Standard_Boolean isFound = Standard_False;
1418 while (!isFound)
1419 {
1420 TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
1421 // Look for objects with default names
1422 if (theObjectMap.IsBound1(aStringKey))
1423 {
1424 aNextKey++;
1425 }
1426 else
1427 isFound = Standard_True;
1428 }
1429
1430 return theDefaultString + TCollection_AsciiString(aNextKey);
1431}
1432
1433//==============================================================================
1434//structure : ViewerTest_Names
1435//purpose : Allow to operate with full view name: driverName/viewerName/viewName
1436//==============================================================================
1437struct ViewerTest_Names
1438{
1439private:
1440 TCollection_AsciiString myDriverName;
1441 TCollection_AsciiString myViewerName;
1442 TCollection_AsciiString myViewName;
1443
1444public:
1445
1446 const TCollection_AsciiString& GetDriverName () const
1447 {
1448 return myDriverName;
1449 }
1450 void SetDriverName (const TCollection_AsciiString& theDriverName)
1451 {
1452 myDriverName = theDriverName;
1453 }
1454 const TCollection_AsciiString& GetViewerName () const
1455 {
1456 return myViewerName;
1457 }
1458 void SetViewerName (const TCollection_AsciiString& theViewerName)
1459 {
1460 myViewerName = theViewerName;
1461 }
1462 const TCollection_AsciiString& GetViewName () const
1463 {
1464 return myViewName;
1465 }
1466 void SetViewName (const TCollection_AsciiString& theViewName)
1467 {
1468 myViewName = theViewName;
1469 }
1470
1471 //===========================================================================
1472 //function : Constructor for ViewerTest_Names
1473 //purpose : Get view, viewer, driver names from custom string
1474 //===========================================================================
1475
1476 ViewerTest_Names (const TCollection_AsciiString& theInputString)
1477 {
1478 TCollection_AsciiString aName(theInputString);
1479 if (theInputString.IsEmpty())
1480 {
1481 // Get current configuration
1482 if (ViewerTest_myDrivers.IsEmpty())
1483 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1484 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1485 else
1486 myDriverName = ViewerTest_myDrivers.Find2
1487 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1488
1489 if(ViewerTest_myContexts.IsEmpty())
1490 {
1491 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1492 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1493 }
1494 else
c48e2889 1495 {
18d715bd 1496 myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
c48e2889 1497 }
18d715bd 1498
c48e2889 1499 myViewName = CreateName <Handle(V3d_View)> (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
18d715bd 1500 }
1501 else
1502 {
1503 // There is at least view name
1504 Standard_Integer aParserNumber = 0;
1505 for (Standard_Integer i = 0; i < 3; ++i)
1506 {
1507 Standard_Integer aParserPos = aName.SearchFromEnd("/");
1508 if(aParserPos != -1)
1509 {
1510 aParserNumber++;
1511 aName.Split(aParserPos-1);
1512 }
1513 else
1514 break;
1515 }
1516 if (aParserNumber == 0)
1517 {
1518 // Only view name
1519 if (!ViewerTest::GetAISContext().IsNull())
1520 {
1521 myDriverName = ViewerTest_myDrivers.Find2
1522 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1523 myViewerName = ViewerTest_myContexts.Find2
1524 (ViewerTest::GetAISContext());
1525 }
1526 else
1527 {
1528 // There is no opened contexts here, need to create names for viewer and driver
1529 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1530 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1531
1532 myViewerName = CreateName <Handle(AIS_InteractiveContext)>
1533 (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
1534 }
1535 myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
1536 }
1537 else if (aParserNumber == 1)
1538 {
1539 // Here is viewerName/viewName
1540 if (!ViewerTest::GetAISContext().IsNull())
1541 myDriverName = ViewerTest_myDrivers.Find2
1542 (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
1543 else
1544 {
1545 // There is no opened contexts here, need to create name for driver
1546 myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
1547 (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
1548 }
1549 myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
1550
1551 myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
1552 }
1553 else
1554 {
1555 //Here is driverName/viewerName/viewName
1556 myDriverName = TCollection_AsciiString(aName);
1557
1558 TCollection_AsciiString aViewerName(theInputString);
1559 aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
1560 myViewerName = TCollection_AsciiString(aViewerName);
1561
1562 myViewName = TCollection_AsciiString(theInputString);
1563 }
1564 }
1565 }
1566};
1567
1568//==============================================================================
1569//function : FindContextByView
1570//purpose : Find AIS_InteractiveContext by View
1571//==============================================================================
1572
1573Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
1574{
1575 Handle(AIS_InteractiveContext) anAISContext;
1576
1577 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1578 anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
1579 {
1580 if (anIter.Value()->CurrentViewer() == theView->Viewer())
1581 return anIter.Key2();
1582 }
1583 return anAISContext;
1584}
1585
18d715bd 1586//==============================================================================
1587//function : IsWindowOverlapped
1588//purpose : Check if theWindow overlapp another view
1589//==============================================================================
1590
1591Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
1592 const Standard_Integer thePxTop,
1593 const Standard_Integer thePxRight,
1594 const Standard_Integer thePxBottom,
1595 TCollection_AsciiString& theViewId)
1596{
1597 for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1598 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1599 {
1600 Standard_Integer aTop = 0,
1601 aLeft = 0,
1602 aRight = 0,
1603 aBottom = 0;
1604 anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
1605 if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1606 (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
1607 (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
1608 (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
1609 {
1610 theViewId = anIter.Key1();
1611 return Standard_True;
1612 }
1613 }
1614 return Standard_False;
1615}
1616
1617// Workaround: to create and delete non-orthographic views outside ViewerTest
1618void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
1619{
1620 ViewerTest_myViews.UnBind1 (theName);
1621}
1622
1623void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
1624 const Handle(V3d_View)& theView)
1625{
1626 ViewerTest_myViews.Bind (theName, theView);
1627}
1628
1629TCollection_AsciiString ViewerTest::GetCurrentViewName ()
1630{
1631 return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
1632}
8693dfd0 1633
1634//! Auxiliary tool performing continuous redraws of specified window.
1635class ViewerTest_ContinuousRedrawer
1636{
1637public:
1638 //! Return global instance.
1639 static ViewerTest_ContinuousRedrawer& Instance()
1640 {
1641 static ViewerTest_ContinuousRedrawer aRedrawer;
1642 return aRedrawer;
1643 }
1644public:
1645
1646 //! Destructor.
1647 ~ViewerTest_ContinuousRedrawer()
1648 {
1649 Stop();
1650 }
1651
1652 //! Start thread.
1653 void Start (const Handle(Aspect_Window)& theWindow,
1654 Standard_Real theTargetFps)
1655 {
1656 if (myWindow != theWindow
1657 || myTargetFps != theTargetFps)
1658 {
1659 Stop();
1660 myWindow = theWindow;
1661 myTargetFps = theTargetFps;
1662 }
1663 if (myThread.GetId() == 0)
1664 {
1665 myToStop = false;
1666 myThread.Run (this);
1667 }
1668 }
1669
1670 //! Stop thread.
1671 void Stop (const Handle(Aspect_Window)& theWindow = NULL)
1672 {
1673 if (!theWindow.IsNull()
1674 && myWindow != theWindow)
1675 {
1676 return;
1677 }
1678
1679 {
1680 Standard_Mutex::Sentry aLock (myMutex);
1681 myToStop = true;
1682 }
1683 myThread.Wait();
1684 myToStop = false;
1685 myWindow.Nullify();
1686 }
1687
1688private:
1689
1690 //! Thread loop.
1691 void doThreadLoop()
1692 {
1693 Handle(Aspect_DisplayConnection) aDisp = new Aspect_DisplayConnection();
1694 OSD_Timer aTimer;
1695 aTimer.Start();
1696 Standard_Real aTimeOld = 0.0;
1697 const Standard_Real aTargetDur = myTargetFps > 0.0 ? 1.0 / myTargetFps : -1.0;
1698 for (;;)
1699 {
1700 {
1701 Standard_Mutex::Sentry aLock (myMutex);
1702 if (myToStop)
1703 {
1704 return;
1705 }
1706 }
1707 if (myTargetFps > 0.0)
1708 {
1709 const Standard_Real aTimeNew = aTimer.ElapsedTime();
1710 const Standard_Real aDuration = aTimeNew - aTimeOld;
1711 if (aDuration >= aTargetDur)
1712 {
1713 myWindow->InvalidateContent (aDisp);
1714 aTimeOld = aTimeNew;
1715 }
1716 }
1717 else
1718 {
1719 myWindow->InvalidateContent (aDisp);
1720 }
1721
1722 OSD::MilliSecSleep (1);
1723 }
1724 }
1725
1726 //! Thread creation callback.
1727 static Standard_Address doThreadWrapper (Standard_Address theData)
1728 {
1729 ViewerTest_ContinuousRedrawer* aThis = (ViewerTest_ContinuousRedrawer* )theData;
1730 aThis->doThreadLoop();
1731 return 0;
1732 }
1733
1734 //! Empty constructor.
1735 ViewerTest_ContinuousRedrawer()
1736 : myThread (doThreadWrapper),
1737 myTargetFps (0.0),
1738 myToStop (false) {}
1739
1740private:
1741 Handle(Aspect_Window) myWindow;
1742 OSD_Thread myThread;
1743 Standard_Mutex myMutex;
1744 Standard_Real myTargetFps;
1745 volatile bool myToStop;
1746};
1747
18d715bd 1748//==============================================================================
7fd59977 1749//function : ViewerInit
1750//purpose : Create the window viewer and initialize all the global variable
1751//==============================================================================
1752
18d715bd 1753TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
1754 const Standard_Integer thePxTop,
1755 const Standard_Integer thePxWidth,
1756 const Standard_Integer thePxHeight,
9e04ccdc 1757 const TCollection_AsciiString& theViewName,
1758 const TCollection_AsciiString& theDisplayName,
1759 const Handle(V3d_View)& theViewToClone)
7fd59977 1760{
8c3c9904 1761 // Default position and dimension of the viewer window.
4fe56619 1762 // Note that left top corner is set to be sufficiently small to have
8c3c9904 1763 // window fit in the small screens (actual for remote desktops, see #23003).
4fe56619 1764 // The position corresponds to the window's client area, thus some
8c3c9904 1765 // gap is added for window frame to be visible.
1766 Standard_Integer aPxLeft = 20;
1767 Standard_Integer aPxTop = 40;
7fd59977 1768 Standard_Integer aPxWidth = 409;
1769 Standard_Integer aPxHeight = 409;
18d715bd 1770 Standard_Boolean toCreateViewer = Standard_False;
9e04ccdc 1771 if (!theViewToClone.IsNull())
1772 {
1773 theViewToClone->Window()->Size (aPxWidth, aPxHeight);
1774 }
18d715bd 1775
58655684 1776 Handle(OpenGl_GraphicDriver) aGraphicDriver;
18d715bd 1777 ViewerTest_Names aViewNames(theViewName);
1778 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
1779 aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
1780
1781 if (thePxLeft != 0)
1782 aPxLeft = thePxLeft;
1783 if (thePxTop != 0)
1784 aPxTop = thePxTop;
1785 if (thePxWidth != 0)
1786 aPxWidth = thePxWidth;
1787 if (thePxHeight != 0)
7fd59977 1788 aPxHeight = thePxHeight;
4269bd1b 1789
18d715bd 1790 // Get graphic driver (create it or get from another view)
8693dfd0 1791 const bool isNewDriver = !ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName());
1792 if (isNewDriver)
18d715bd 1793 {
1794 // Get connection string
58655684 1795 #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
8693dfd0 1796 if (!theDisplayName.IsEmpty())
1797 {
1798 SetDisplayConnection (new Aspect_DisplayConnection (theDisplayName));
1799 }
18d715bd 1800 else
8693dfd0 1801 {
1802 ::Display* aDispX = NULL;
1803 // create dedicated display connection instead of reusing Tk connection
1804 // so that to procede events independently through VProcessEvents()/ViewerMainLoop() callbacks
1805 /*Draw_Interpretor& aCommands = Draw::GetInterpretor();
1806 Tcl_Interp* aTclInterp = aCommands.Interp();
1807 Tk_Window aMainWindow = Tk_MainWindow (aTclInterp);
1808 aDispX = aMainWindow != NULL ? Tk_Display (aMainWindow) : NULL;*/
1809 SetDisplayConnection (new Aspect_DisplayConnection (aDispX));
1810 }
18d715bd 1811 #else
498ce76b 1812 (void)theDisplayName; // avoid warning on unused argument
18d715bd 1813 SetDisplayConnection (new Aspect_DisplayConnection ());
1814 #endif
14cb22a1 1815
1816 if (Draw_VirtualWindows)
1817 {
1818 // don't waste the time waiting for VSync when window is not displayed on the screen
1819 ViewerTest_myDefaultCaps.swapInterval = 0;
1820 // alternatively we can disable buffer swap at all, but this might be inappropriate for testing
1821 //ViewerTest_myDefaultCaps.buffersNoSwap = true;
1822 }
59515ca6 1823 aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection(), false);
58655684 1824 aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
59515ca6 1825 aGraphicDriver->InitContext();
14cb22a1 1826
18d715bd 1827 ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
1828 toCreateViewer = Standard_True;
1829 }
1830 else
1831 {
58655684 1832 aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
7fd59977 1833 }
1834
18d715bd 1835 //Dispose the window if input parameters are default
1836 if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
7fd59977 1837 {
18d715bd 1838 Standard_Integer aTop = 0,
1839 aLeft = 0,
1840 aRight = 0,
1841 aBottom = 0,
1842 aScreenWidth = 0,
1843 aScreenHeight = 0;
1844
1845 // Get screen resolution
1846#if defined(_WIN32) || defined(__WIN32__)
1847 RECT aWindowSize;
1848 GetClientRect(GetDesktopWindow(), &aWindowSize);
1849 aScreenHeight = aWindowSize.bottom;
1850 aScreenWidth = aWindowSize.right;
1851#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1852 GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
1853#else
1854 Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
1855 aScreenWidth = WidthOfScreen(aScreen);
1856 aScreenHeight = HeightOfScreen(aScreen);
1857#endif
1858
1859 TCollection_AsciiString anOverlappedViewId("");
773f53f1 1860
1861 while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
dc3fe572 1862 {
18d715bd 1863 ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
1864
1865 if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
1866 && aRight + 2*aPxWidth + 40 > aScreenWidth)
1867 {
1868 if (aBottom + aPxHeight + 40 > aScreenHeight)
1869 {
1870 aPxLeft = 20;
1871 aPxTop = 40;
1872 break;
1873 }
1874 aPxLeft = 20;
1875 aPxTop = aBottom + 40;
1876 }
1877 else
1878 aPxLeft = aRight + 20;
dc3fe572 1879 }
18d715bd 1880 }
1881
1882 // Get viewer name
1883 TCollection_AsciiString aTitle("3D View - ");
1884 aTitle = aTitle + aViewNames.GetViewName() + "(*)";
1885
1886 // Change name of current active window
49582f9d 1887 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
18d715bd 1888 {
49582f9d 1889 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
18d715bd 1890 }
1891
1892 // Create viewer
eb4320f2 1893 Handle(V3d_Viewer) a3DViewer;
18d715bd 1894 // If it's the single view, we first look for empty context
1895 if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
1896 {
1897 NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1898 anIter(ViewerTest_myContexts);
1899 if (anIter.More())
1900 ViewerTest::SetAISContext (anIter.Value());
1901 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 1902 }
1903 else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
1904 {
1905 ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
1906 a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
18d715bd 1907 }
eb4320f2 1908 else if (a3DViewer.IsNull())
18d715bd 1909 {
1910 toCreateViewer = Standard_True;
6a24c6de 1911 a3DViewer = new V3d_Viewer(aGraphicDriver);
f42753ed 1912 a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
1913 a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
1914 ViewerTest_DefaultBackground.GradientColor2,
1915 ViewerTest_DefaultBackground.FillMethod);
18d715bd 1916 }
1917
1918 // AIS context setup
1919 if (ViewerTest::GetAISContext().IsNull() ||
1920 !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
1921 {
e79a94b9 1922 Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
18d715bd 1923 ViewerTest::SetAISContext (aContext);
1924 ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
1925 }
1926 else
e79a94b9 1927 {
18d715bd 1928 ViewerTest::ResetEventManager();
e79a94b9 1929 }
18d715bd 1930
1931 // Create window
e79a94b9 1932#if defined(_WIN32)
1933 VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
1934 Handle(WNT_WClass)::DownCast (WClass()),
62e1beed 1935 Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
e79a94b9 1936 aPxLeft, aPxTop,
1937 aPxWidth, aPxHeight,
1938 Quantity_NOC_BLACK);
4fe56619 1939#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
e79a94b9 1940 VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
1941 aPxLeft, aPxTop,
1942 aPxWidth, aPxHeight);
1943 ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
7fd59977 1944#else
e79a94b9 1945 VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
1946 aTitle.ToCString(),
1947 aPxLeft, aPxTop,
1948 aPxWidth, aPxHeight);
7fd59977 1949#endif
18d715bd 1950 VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
7fd59977 1951
d09dda09 1952 // View setup
9e04ccdc 1953 Handle(V3d_View) aView;
1954 if (!theViewToClone.IsNull())
1955 {
2e93433e 1956 aView = new ViewerTest_V3dView (a3DViewer, theViewToClone);
9e04ccdc 1957 }
1958 else
1959 {
2e93433e 1960 aView = new ViewerTest_V3dView (a3DViewer, a3DViewer->DefaultTypeOfView());
9e04ccdc 1961 }
1962
d09dda09 1963 aView->SetWindow (VT_GetWindow());
c3282ec1 1964 ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
4269bd1b 1965
18d715bd 1966 ViewerTest::CurrentView(aView);
1967 ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
7fd59977 1968
18d715bd 1969 // Setup for X11 or NT
1970 OSWindowSetup();
7fd59977 1971
18d715bd 1972 // Set parameters for V3d_View and V3d_Viewer
1973 const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
1974 aV3dView->SetComputedMode(Standard_False);
7fd59977 1975
18d715bd 1976 a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
1977 if (toCreateViewer)
1978 {
7fd59977 1979 a3DViewer->SetDefaultLights();
1980 a3DViewer->SetLightOn();
18d715bd 1981 }
7fd59977 1982
8693dfd0 1983#if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1984 if (isNewDriver)
1985 {
1986 ::Display* aDispX = GetDisplayConnection()->GetDisplay();
1987 Tcl_CreateFileHandler (XConnectionNumber (aDispX), TCL_READABLE, VProcessEvents, (ClientData )aDispX);
1988 }
1989#endif
7fd59977 1990
7fd59977 1991 VT_GetWindow()->Map();
4269bd1b 1992
18d715bd 1993 // Set the handle of created view in the event manager
1994 ViewerTest::ResetEventManager();
1995
4fe56619 1996 ViewerTest::CurrentView()->Redraw();
18d715bd 1997
1998 aView.Nullify();
1999 a3DViewer.Nullify();
18d715bd 2000
2001 return aViewNames.GetViewName();
2002}
2003
2004//==============================================================================
4269bd1b 2005//function : RedrawAllViews
2006//purpose : Redraw all created views
2007//==============================================================================
2008void ViewerTest::RedrawAllViews()
2009{
2010 NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
2011 for (; aViewIt.More(); aViewIt.Next())
2012 {
2013 const Handle(V3d_View)& aView = aViewIt.Key2();
2014 aView->Redraw();
2015 }
2016}
2017
2018//==============================================================================
7fd59977 2019//function : Vinit
2020//purpose : Create the window viewer and initialize all the global variable
e79a94b9 2021// Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
7fd59977 2022//==============================================================================
2023
18d715bd 2024static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
7fd59977 2025{
e79a94b9 2026 TCollection_AsciiString aViewName, aDisplayName;
2027 Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
9e04ccdc 2028 Handle(V3d_View) aCopyFrom;
e79a94b9 2029 TCollection_AsciiString aName, aValue;
2e93433e 2030 int is2dMode = -1;
e79a94b9 2031 for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
18d715bd 2032 {
e79a94b9 2033 const TCollection_AsciiString anArg = theArgVec[anArgIt];
2034 TCollection_AsciiString anArgCase = anArg;
fd3f6bd0 2035 anArgCase.LowerCase();
2036 if (anArgIt + 1 < theArgsNb
2037 && anArgCase == "-name")
2038 {
2039 aViewName = theArgVec[++anArgIt];
2040 }
2041 else if (anArgIt + 1 < theArgsNb
2042 && (anArgCase == "-left"
2043 || anArgCase == "-l"))
2044 {
2045 aPxLeft = Draw::Atoi (theArgVec[++anArgIt]);
2046 }
2047 else if (anArgIt + 1 < theArgsNb
2048 && (anArgCase == "-top"
2049 || anArgCase == "-t"))
2050 {
2051 aPxTop = Draw::Atoi (theArgVec[++anArgIt]);
2052 }
2053 else if (anArgIt + 1 < theArgsNb
2054 && (anArgCase == "-width"
2055 || anArgCase == "-w"))
2056 {
2057 aPxWidth = Draw::Atoi (theArgVec[++anArgIt]);
2058 }
2059 else if (anArgIt + 1 < theArgsNb
2060 && (anArgCase == "-height"
2061 || anArgCase == "-h"))
18d715bd 2062 {
fd3f6bd0 2063 aPxHeight = Draw::Atoi (theArgVec[++anArgIt]);
2064 }
2065 else if (anArgCase == "-exitonclose")
2066 {
49582f9d 2067 ViewerTest_EventManager::ToExitOnCloseView() = true;
fd3f6bd0 2068 if (anArgIt + 1 < theArgsNb
49582f9d 2069 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToExitOnCloseView()))
fd3f6bd0 2070 {
2071 ++anArgIt;
2072 }
2073 }
2074 else if (anArgCase == "-closeonescape"
2075 || anArgCase == "-closeonesc")
2076 {
49582f9d 2077 ViewerTest_EventManager::ToCloseViewOnEscape() = true;
fd3f6bd0 2078 if (anArgIt + 1 < theArgsNb
49582f9d 2079 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], ViewerTest_EventManager::ToCloseViewOnEscape()))
fd3f6bd0 2080 {
2081 ++anArgIt;
2082 }
2083 }
2e93433e 2084 else if (anArgCase == "-2d_mode"
2085 || anArgCase == "-2dmode"
2086 || anArgCase == "-2d")
2087 {
2088 bool toEnable = true;
2089 if (anArgIt + 1 < theArgsNb
2090 && ViewerTest::ParseOnOff (theArgVec[anArgIt + 1], toEnable))
2091 {
2092 ++anArgIt;
2093 }
2094 is2dMode = toEnable ? 1 : 0;
2095 }
fd3f6bd0 2096 else if (anArgIt + 1 < theArgsNb
2097 && (anArgCase == "-disp"
2098 || anArgCase == "-display"))
2099 {
2100 aDisplayName = theArgVec[++anArgIt];
2101 }
9e04ccdc 2102 else if (!ViewerTest::CurrentView().IsNull()
2103 && aCopyFrom.IsNull()
2104 && (anArgCase == "-copy"
2105 || anArgCase == "-clone"
2106 || anArgCase == "-cloneactive"
2107 || anArgCase == "-cloneactiveview"))
2108 {
2109 aCopyFrom = ViewerTest::CurrentView();
2110 }
fd3f6bd0 2111 // old syntax
2112 else if (ViewerTest::SplitParameter (anArg, aName, aValue))
2113 {
2114 aName.LowerCase();
2115 if (aName == "name")
18d715bd 2116 {
2117 aViewName = aValue;
2118 }
fd3f6bd0 2119 else if (aName == "l"
2120 || aName == "left")
e79a94b9 2121 {
18d715bd 2122 aPxLeft = aValue.IntegerValue();
e79a94b9 2123 }
fd3f6bd0 2124 else if (aName == "t"
2125 || aName == "top")
e79a94b9 2126 {
18d715bd 2127 aPxTop = aValue.IntegerValue();
e79a94b9 2128 }
fd3f6bd0 2129 else if (aName == "disp"
2130 || aName == "display")
e79a94b9 2131 {
18d715bd 2132 aDisplayName = aValue;
e79a94b9 2133 }
fd3f6bd0 2134 else if (aName == "w"
2135 || aName == "width")
e79a94b9 2136 {
18d715bd 2137 aPxWidth = aValue.IntegerValue();
e79a94b9 2138 }
fd3f6bd0 2139 else if (aName == "h"
2140 || aName == "height")
e79a94b9 2141 {
18d715bd 2142 aPxHeight = aValue.IntegerValue();
e79a94b9 2143 }
18d715bd 2144 else
2145 {
fd3f6bd0 2146 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2147 return 1;
18d715bd 2148 }
2149 }
e79a94b9 2150 else if (aViewName.IsEmpty())
2151 {
2152 aViewName = anArg;
2153 }
2154 else
2155 {
fd3f6bd0 2156 std::cout << "Syntax error: unknown argument " << anArg << ".\n";
2157 return 1;
e79a94b9 2158 }
18d715bd 2159 }
2160
fd3f6bd0 2161#if defined(_WIN32) || (defined(__APPLE__) && !defined(MACOSX_USE_GLX))
2162 if (!aDisplayName.IsEmpty())
2163 {
2164 aDisplayName.Clear();
2165 std::cout << "Warning: display parameter will be ignored.\n";
2166 }
2167#endif
2168
18d715bd 2169 ViewerTest_Names aViewNames (aViewName);
e79a94b9 2170 if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
18d715bd 2171 {
e79a94b9 2172 TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
2173 theDi.Eval (aCommand.ToCString());
2e93433e 2174 if (is2dMode != -1)
2175 {
2176 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2177 }
18d715bd 2178 return 0;
2179 }
2180
2181 TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
9e04ccdc 2182 aViewName, aDisplayName, aCopyFrom);
2e93433e 2183 if (is2dMode != -1)
2184 {
2185 ViewerTest_V3dView::SetCurrentView2DMode (is2dMode == 1);
2186 }
e79a94b9 2187 theDi << aViewId;
7fd59977 2188 return 0;
2189}
2190
1eeef710 2191//! Parse HLR algo type.
2192static Standard_Boolean parseHlrAlgoType (const char* theName,
2193 Prs3d_TypeOfHLR& theType)
2194{
2195 TCollection_AsciiString aName (theName);
2196 aName.LowerCase();
2197 if (aName == "polyalgo")
2198 {
2199 theType = Prs3d_TOH_PolyAlgo;
2200 }
2201 else if (aName == "algo")
2202 {
2203 theType = Prs3d_TOH_Algo;
2204 }
2205 else
2206 {
2207 return Standard_False;
2208 }
2209 return Standard_True;
2210}
2211
7fd59977 2212//==============================================================================
0a768f56 2213//function : VHLR
2214//purpose : hidden lines removal algorithm
2215//==============================================================================
2216
2217static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2218{
1eeef710 2219 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2220 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2221 if (aView.IsNull())
0a768f56 2222 {
1eeef710 2223 std::cerr << "Error: No opened viewer!\n";
0a768f56 2224 return 1;
2225 }
2226
1eeef710 2227 Standard_Boolean hasHlrOnArg = Standard_False;
2228 Standard_Boolean hasShowHiddenArg = Standard_False;
2229 Standard_Boolean isHLROn = Standard_False;
2230 Standard_Boolean toShowHidden = aCtx->DefaultDrawer()->DrawHiddenLine();
2231 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2232 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2233 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 2234 {
1eeef710 2235 TCollection_AsciiString anArg (argv[anArgIter]);
2236 anArg.LowerCase();
2237 if (anUpdateTool.parseRedrawMode (anArg))
2238 {
2239 continue;
2240 }
2241 else if (anArg == "-showhidden"
2242 && anArgIter + 1 < argc
2243 && ViewerTest::ParseOnOff (argv[anArgIter + 1], toShowHidden))
2244 {
2245 ++anArgIter;
2246 hasShowHiddenArg = Standard_True;
2247 continue;
2248 }
2249 else if ((anArg == "-type"
2250 || anArg == "-algo"
2251 || anArg == "-algotype")
2252 && anArgIter + 1 < argc
2253 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2254 {
2255 ++anArgIter;
2256 continue;
2257 }
2258 else if (!hasHlrOnArg
2259 && ViewerTest::ParseOnOff (argv[anArgIter], isHLROn))
2260 {
2261 hasHlrOnArg = Standard_True;
2262 continue;
2263 }
2264 // old syntax
2265 else if (!hasShowHiddenArg
2266 && ViewerTest::ParseOnOff(argv[anArgIter], toShowHidden))
2267 {
2268 hasShowHiddenArg = Standard_True;
2269 continue;
2270 }
2271 else
2272 {
2273 std::cout << "Syntax error at '" << argv[anArgIter] << "'\n";
2274 return 1;
2275 }
0a768f56 2276 }
1eeef710 2277 if (!hasHlrOnArg)
0a768f56 2278 {
1eeef710 2279 di << "HLR: " << aView->ComputedMode() << "\n";
2280 di << "HiddenLine: " << aCtx->DefaultDrawer()->DrawHiddenLine() << "\n";
2281 di << "HlrAlgo: ";
2282 switch (aCtx->DefaultDrawer()->TypeOfHLR())
2283 {
2284 case Prs3d_TOH_NotSet: di << "NotSet\n"; break;
2285 case Prs3d_TOH_PolyAlgo: di << "PolyAlgo\n"; break;
2286 case Prs3d_TOH_Algo: di << "Algo\n"; break;
2287 }
2288 anUpdateTool.Invalidate();
2289 return 0;
0a768f56 2290 }
2291
1eeef710 2292 Standard_Boolean toRecompute = Standard_False;
2293 if (aTypeOfHLR != Prs3d_TOH_NotSet
2294 && aTypeOfHLR != aCtx->DefaultDrawer()->TypeOfHLR())
e9224045 2295 {
1eeef710 2296 toRecompute = Standard_True;
2297 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
2298 }
2299 if (toShowHidden != aCtx->DefaultDrawer()->DrawHiddenLine())
2300 {
2301 toRecompute = Standard_True;
2302 if (toShowHidden)
e9224045 2303 {
1eeef710 2304 aCtx->DefaultDrawer()->EnableDrawHiddenLine();
e9224045 2305 }
2306 else
2307 {
1eeef710 2308 aCtx->DefaultDrawer()->DisableDrawHiddenLine();
e9224045 2309 }
1eeef710 2310 }
e9224045 2311
1eeef710 2312 // redisplay shapes
2313 if (aView->ComputedMode() && isHLROn && toRecompute)
2314 {
2315 AIS_ListOfInteractive aListOfShapes;
2316 aCtx->DisplayedObjects (aListOfShapes);
2317 for (AIS_ListIteratorOfListOfInteractive anIter (aListOfShapes); anIter.More(); anIter.Next())
e9224045 2318 {
1eeef710 2319 if (Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value()))
e9224045 2320 {
1eeef710 2321 aCtx->Redisplay (aShape, Standard_False);
e9224045 2322 }
2323 }
2324 }
0a768f56 2325
1eeef710 2326 aView->SetComputedMode (isHLROn);
0a768f56 2327 return 0;
2328}
2329
2330//==============================================================================
2331//function : VHLRType
2332//purpose : change type of using HLR algorithm
2333//==============================================================================
2334
1eeef710 2335static int VHLRType (Draw_Interpretor& , Standard_Integer argc, const char** argv)
0a768f56 2336{
1eeef710 2337 const Handle(V3d_View) aView = ViewerTest::CurrentView();
2338 const Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
2339 if (aView.IsNull())
0a768f56 2340 {
1eeef710 2341 std::cerr << "Error: No opened viewer!\n";
0a768f56 2342 return 1;
2343 }
2344
1eeef710 2345 Prs3d_TypeOfHLR aTypeOfHLR = Prs3d_TOH_NotSet;
2346 ViewerTest_AutoUpdater anUpdateTool (Handle(AIS_InteractiveContext)(), aView);
2347 AIS_ListOfInteractive aListOfShapes;
2348 for (Standard_Integer anArgIter = 1; anArgIter < argc; ++anArgIter)
0a768f56 2349 {
1eeef710 2350 TCollection_AsciiString anArg (argv[anArgIter]);
2351 anArg.LowerCase();
2352 if (anUpdateTool.parseRedrawMode (anArg))
0a768f56 2353 {
1eeef710 2354 continue;
0a768f56 2355 }
1eeef710 2356 else if ((anArg == "-type"
2357 || anArg == "-algo"
2358 || anArg == "-algotype")
2359 && anArgIter + 1 < argc
2360 && parseHlrAlgoType (argv[anArgIter + 1], aTypeOfHLR))
2361 {
2362 ++anArgIter;
2363 continue;
2364 }
2365 // old syntax
2366 else if (aTypeOfHLR == Prs3d_TOH_NotSet
2367 && parseHlrAlgoType (argv[anArgIter], aTypeOfHLR))
2368 {
2369 continue;
2370 }
2371 else
0a768f56 2372 {
2373 ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
1eeef710 2374 TCollection_AsciiString aName (argv[anArgIter]);
0a768f56 2375 if (!aMap.IsBound2 (aName))
2376 {
1eeef710 2377 std::cout << "Syntax error: Wrong shape name '" << aName << "'.\n";
2378 return 1;
0a768f56 2379 }
1eeef710 2380
2381 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (aMap.Find2 (aName));
2382 if (aShape.IsNull())
2383 {
2384 std::cout << "Syntax error: '" << aName << "' is not a shape presentation.\n";
2385 return 1;
2386 }
2387 aListOfShapes.Append (aShape);
2388 continue;
0a768f56 2389 }
1eeef710 2390 }
2391 if (aTypeOfHLR == Prs3d_TOH_NotSet)
2392 {
2393 std::cout << "Syntax error: wrong number of arguments!\n";
2394 return 1;
2395 }
2396
2397 const Standard_Boolean isGlobal = aListOfShapes.IsEmpty();
2398 if (isGlobal)
2399 {
2400 aCtx->DisplayedObjects (aListOfShapes);
2401 aCtx->DefaultDrawer()->SetTypeOfHLR (aTypeOfHLR);
0a768f56 2402 }
2403
1eeef710 2404 for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
2405 {
2406 Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
2407 if (aShape.IsNull())
2408 {
2409 continue;
2410 }
2411
2412 const bool toUpdateShape = aShape->TypeOfHLR() != aTypeOfHLR
2413 && aView->ComputedMode();
2414 if (!isGlobal
2415 || aShape->TypeOfHLR() != aTypeOfHLR)
2416 {
2417 aShape->SetTypeOfHLR (aTypeOfHLR);
2418 }
2419 if (toUpdateShape)
2420 {
2421 aCtx->Redisplay (aShape, Standard_False);
2422 }
2423 }
0a768f56 2424 return 0;
2425}
2426
2427//==============================================================================
18d715bd 2428//function : FindViewIdByWindowHandle
2429//purpose : Find theView Id in the map of views by window handle
2430//==============================================================================
49582f9d 2431#if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2432TCollection_AsciiString FindViewIdByWindowHandle (Aspect_Drawable theWindowHandle)
18d715bd 2433{
2434 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
2435 anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
2436 {
49582f9d 2437 Aspect_Drawable aWindowHandle = anIter.Value()->Window()->NativeHandle();
18d715bd 2438 if (aWindowHandle == theWindowHandle)
2439 return anIter.Key1();
2440 }
2441 return TCollection_AsciiString("");
2442}
2443#endif
2444
e084dbbc 2445//! Make the view active
2446void ActivateView (const TCollection_AsciiString& theViewName,
2447 Standard_Boolean theToUpdate = Standard_True)
18d715bd 2448{
2449 const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
e084dbbc 2450 if (aView.IsNull())
18d715bd 2451 {
e084dbbc 2452 return;
2453 }
18d715bd 2454
e084dbbc 2455 Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
2456 if (!anAISContext.IsNull())
2457 {
49582f9d 2458 if (const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView())
e084dbbc 2459 {
49582f9d 2460 aCurrentView->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (aCurrentView));
e084dbbc 2461 }
2462
2463 ViewerTest::CurrentView (aView);
2464 ViewerTest::SetAISContext (anAISContext);
49582f9d 2465 aView->Window()->SetTitle (TCollection_AsciiString("3D View - ") + theViewName + "(*)");
1eeef710 2466#if defined(_WIN32)
e084dbbc 2467 VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2468#elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
e084dbbc 2469 VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2470#else
e084dbbc 2471 VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
18d715bd 2472#endif
e084dbbc 2473 SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2474 if (theToUpdate)
2475 {
18d715bd 2476 ViewerTest::CurrentView()->Redraw();
2477 }
2478 }
2479}
2480
2481//==============================================================================
2482//function : RemoveView
0e93d9e5 2483//purpose :
2484//==============================================================================
2485void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
2486 const Standard_Boolean theToRemoveContext)
2487{
2488 if (!ViewerTest_myViews.IsBound2 (theView))
2489 {
2490 return;
2491 }
2492
2493 const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
2494 RemoveView (aViewName, theToRemoveContext);
2495}
2496
2497//==============================================================================
2498//function : RemoveView
18d715bd 2499//purpose : Close and remove view from display, clear maps if neccessary
2500//==============================================================================
2501void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
2502{
2503 if (!ViewerTest_myViews.IsBound1(theViewName))
2504 {
04232180 2505 std::cout << "Wrong view name\n";
18d715bd 2506 return;
2507 }
2508
2509 // Activate another view if it's active now
2510 if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
2511 {
2512 if (ViewerTest_myViews.Extent() > 1)
2513 {
2514 TCollection_AsciiString aNewViewName;
c48e2889 2515 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2516 anIter.More(); anIter.Next())
2517 {
18d715bd 2518 if (anIter.Key1() != theViewName)
2519 {
2520 aNewViewName = anIter.Key1();
2521 break;
2522 }
c48e2889 2523 }
2524 ActivateView (aNewViewName);
18d715bd 2525 }
2526 else
2527 {
e084dbbc 2528 VT_GetWindow().Nullify();
2529 ViewerTest::CurrentView (Handle(V3d_View)());
18d715bd 2530 if (isContextRemoved)
2531 {
2532 Handle(AIS_InteractiveContext) anEmptyContext;
2533 ViewerTest::SetAISContext(anEmptyContext);
2534 }
2535 }
2536 }
2537
2538 // Delete view
2539 Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
2540 Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
8693dfd0 2541 ViewerTest_ContinuousRedrawer& aRedrawer = ViewerTest_ContinuousRedrawer::Instance();
2542 aRedrawer.Stop (aView->Window());
18d715bd 2543
2544 // Remove view resources
18d715bd 2545 ViewerTest_myViews.UnBind1(theViewName);
851dacdb 2546 aView->Window()->Unmap();
18d715bd 2547 aView->Remove();
2548
2549#if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2550 XFlush (GetDisplayConnection()->GetDisplay());
2551#endif
2552
2553 // Keep context opened only if the closed view is last to avoid
2554 // unused empty contexts
2555 if (!aCurrentContext.IsNull())
2556 {
2557 // Check if there are more difined views in the viewer
2558 aCurrentContext->CurrentViewer()->InitDefinedViews();
2559 if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
2560 {
2561 // Remove driver if there is no viewers that use it
2562 Standard_Boolean isRemoveDriver = Standard_True;
2563 for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2564 anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
2565 {
2566 if (aCurrentContext != anIter.Key2() &&
2567 aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
2568 {
2569 isRemoveDriver = Standard_False;
2570 break;
2571 }
2572 }
2ec85268 2573
2574 aCurrentContext->RemoveAll (Standard_False);
18d715bd 2575 if(isRemoveDriver)
2576 {
2577 ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
2578 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
8693dfd0 2579 Tcl_DeleteFileHandler (XConnectionNumber (aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
18d715bd 2580 #endif
2581 }
2582
2583 ViewerTest_myContexts.UnBind2(aCurrentContext);
2584 }
2585 }
04232180 2586 std::cout << "3D View - " << theViewName << " was deleted.\n";
49582f9d 2587 if (ViewerTest_EventManager::ToExitOnCloseView())
fd3f6bd0 2588 {
2589 Draw_Interprete ("exit");
2590 }
18d715bd 2591}
2592
2593//==============================================================================
2594//function : VClose
2595//purpose : Remove the view defined by its name
2596//==============================================================================
2597
d0cc1cb7 2598static int VClose (Draw_Interpretor& /*theDi*/,
2599 Standard_Integer theArgsNb,
2600 const char** theArgVec)
18d715bd 2601{
18d715bd 2602 NCollection_List<TCollection_AsciiString> aViewList;
d0cc1cb7 2603 if (theArgsNb > 1)
18d715bd 2604 {
d0cc1cb7 2605 TCollection_AsciiString anArg (theArgVec[1]);
2606 anArg.UpperCase();
2607 if (anArg.IsEqual ("ALL")
2608 || anArg.IsEqual ("*"))
2609 {
2610 for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
2611 anIter.More(); anIter.Next())
2612 {
2613 aViewList.Append (anIter.Key1());
2614 }
2615 if (aViewList.IsEmpty())
2616 {
2617 std::cout << "No view to close\n";
2618 return 0;
2619 }
2620 }
2621 else
18d715bd 2622 {
d0cc1cb7 2623 ViewerTest_Names aViewName (theArgVec[1]);
2624 if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
2625 {
2626 std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
2627 return 1;
2628 }
2629 aViewList.Append (aViewName.GetViewName());
18d715bd 2630 }
2631 }
2632 else
2633 {
d0cc1cb7 2634 // close active view
2635 if (ViewerTest::CurrentView().IsNull())
2636 {
2637 std::cerr << "No active view!\n";
2638 return 1;
2639 }
2640 aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
18d715bd 2641 }
2642
d0cc1cb7 2643 Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
18d715bd 2644 for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
2645 anIter.More(); anIter.Next())
2646 {
d0cc1cb7 2647 ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
18d715bd 2648 }
2649
2650 return 0;
2651}
2652
2653//==============================================================================
2654//function : VActivate
2655//purpose : Activate the view defined by its ID
2656//==============================================================================
2657
2658static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2659{
e084dbbc 2660 if (theArgsNb == 1)
18d715bd 2661 {
2662 theDi.Eval("vviewlist");
2663 return 0;
2664 }
2665
e084dbbc 2666 TCollection_AsciiString aNameString;
2667 Standard_Boolean toUpdate = Standard_True;
2668 Standard_Boolean toActivate = Standard_True;
2669 for (Standard_Integer anArgIter = 1; anArgIter < theArgsNb; ++anArgIter)
18d715bd 2670 {
e084dbbc 2671 TCollection_AsciiString anArg (theArgVec[anArgIter]);
2672 anArg.LowerCase();
2673 if (toUpdate
2674 && anArg == "-noupdate")
2675 {
2676 toUpdate = Standard_False;
2677 }
2678 else if (toActivate
2679 && aNameString.IsEmpty()
2680 && anArg == "none")
2681 {
49582f9d 2682 ViewerTest::CurrentView()->Window()->SetTitle (TCollection_AsciiString ("3D View - ") + ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
e084dbbc 2683 VT_GetWindow().Nullify();
2684 ViewerTest::CurrentView (Handle(V3d_View)());
2685 ViewerTest::ResetEventManager();
2686 theDi << theArgVec[0] << ": all views are inactive\n";
2687 toActivate = Standard_False;
2688 }
2689 else if (toActivate
2690 && aNameString.IsEmpty())
2691 {
2692 aNameString = theArgVec[anArgIter];
2693 }
2694 else
2695 {
2696 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
2697 return 1;
2698 }
18d715bd 2699 }
2700
e084dbbc 2701 if (!toActivate)
2702 {
2703 return 0;
2704 }
2705 else if (aNameString.IsEmpty())
2706 {
2707 std::cout << "Syntax error: wrong number of arguments\n";
2708 return 1;
2709 }
18d715bd 2710
2711 // Check if this view exists in the viewer with the driver
e084dbbc 2712 ViewerTest_Names aViewNames (aNameString);
18d715bd 2713 if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
2714 {
e084dbbc 2715 theDi << "Syntax error: wrong view name '" << aNameString << "'\n";
18d715bd 2716 return 1;
2717 }
2718
2719 // Check if it is active already
2720 if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
2721 {
2722 theDi << theArgVec[0] << ": the view is active already\n";
2723 return 0;
2724 }
2725
e084dbbc 2726 ActivateView (aViewNames.GetViewName(), toUpdate);
18d715bd 2727 return 0;
2728}
2729
2730//==============================================================================
2731//function : VViewList
2732//purpose : Print current list of views per viewer and graphic driver ID
2733// shared between viewers
2734//==============================================================================
2735
2736static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
2737{
2738 if (theArgsNb > 2)
2739 {
2740 theDi << theArgVec[0] << ": Wrong number of command arguments\n"
29cb310a 2741 << "Usage: " << theArgVec[0] << " name";
18d715bd 2742 return 1;
2743 }
2744 if (ViewerTest_myContexts.Size() < 1)
2745 return 0;
2746
18d715bd 2747 Standard_Boolean isTreeView =
29cb310a 2748 (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
18d715bd 2749
2750 if (isTreeView)
c48e2889 2751 {
18d715bd 2752 theDi << theArgVec[0] <<":\n";
c48e2889 2753 }
18d715bd 2754
c48e2889 2755 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator aDriverIter (ViewerTest_myDrivers);
2756 aDriverIter.More(); aDriverIter.Next())
2757 {
2758 if (isTreeView)
2759 theDi << aDriverIter.Key1() << ":\n";
18d715bd 2760
c48e2889 2761 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2762 aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
2763 {
2764 if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
18d715bd 2765 {
c48e2889 2766 if (isTreeView)
18d715bd 2767 {
c48e2889 2768 TCollection_AsciiString aContextName(aContextIter.Key1());
2769 theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
2770 }
18d715bd 2771
c48e2889 2772 for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIter (ViewerTest_myViews);
2773 aViewIter.More(); aViewIter.Next())
2774 {
2775 if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
18d715bd 2776 {
c48e2889 2777 TCollection_AsciiString aViewName(aViewIter.Key1());
2778 if (isTreeView)
18d715bd 2779 {
c48e2889 2780 if (aViewIter.Value() == ViewerTest::CurrentView())
2781 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
18d715bd 2782 else
c48e2889 2783 theDi << " " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
2784 }
2785 else
2786 {
2787 theDi << aViewName << " ";
18d715bd 2788 }
2789 }
2790 }
2791 }
2792 }
c48e2889 2793 }
18d715bd 2794 return 0;
2795}
2796
2797//==============================================================================
49582f9d 2798//function : GetMousePosition
2799//purpose :
7fd59977 2800//==============================================================================
49582f9d 2801void ViewerTest::GetMousePosition (Standard_Integer& theX,
2802 Standard_Integer& theY)
7fd59977 2803{
49582f9d 2804 if (Handle(ViewerTest_EventManager) aViewCtrl = ViewerTest::CurrentEventManager())
4fe56619 2805 {
49582f9d 2806 theX = aViewCtrl->LastMousePosition().x();
2807 theY = aViewCtrl->LastMousePosition().y();
4fe56619 2808 }
7fd59977 2809}
2810
2811//==============================================================================
fc552d84 2812//function : VViewProj
2813//purpose : Switch view projection
44b8f2d6 2814//==============================================================================
fc552d84 2815static int VViewProj (Draw_Interpretor& ,
2816 Standard_Integer theNbArgs,
2817 const char** theArgVec)
44b8f2d6 2818{
fc552d84 2819 static Standard_Boolean isYup = Standard_False;
2820 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
2821 if (aView.IsNull())
44b8f2d6 2822 {
fc552d84 2823 std::cout << "Error: no active view\n";
44b8f2d6 2824 return 1;
2825 }
2826
fc552d84 2827 TCollection_AsciiString aCmdName (theArgVec[0]);
2828 Standard_Boolean isGeneralCmd = Standard_False;
2829 if (aCmdName == "vfront")
2830 {
2831 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2832 }
2833 else if (aCmdName == "vback")
2834 {
2835 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2836 }
2837 else if (aCmdName == "vtop")
2838 {
2839 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2840 }
2841 else if (aCmdName == "vbottom")
2842 {
2843 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2844 }
2845 else if (aCmdName == "vleft")
2846 {
2847 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2848 }
2849 else if (aCmdName == "vright")
2850 {
2851 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2852 }
2853 else if (aCmdName == "vaxo")
2854 {
2855 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2856 }
2857 else
2858 {
2859 isGeneralCmd = Standard_True;
2860 for (Standard_Integer anArgIter = 1; anArgIter < theNbArgs; ++anArgIter)
2861 {
2862 TCollection_AsciiString anArgCase (theArgVec[anArgIter]);
2863 anArgCase.LowerCase();
2864 if (anArgCase == "-zup")
2865 {
2866 isYup = Standard_False;
2867 }
2868 else if (anArgCase == "-yup")
2869 {
2870 isYup = Standard_True;
2871 }
2872 else if (anArgCase == "-front"
2873 || anArgCase == "front"
2874 || anArgCase == "-f"
2875 || anArgCase == "f")
2876 {
2877 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Front : V3d_TypeOfOrientation_Zup_Front, isYup);
2878 }
2879 else if (anArgCase == "-back"
2880 || anArgCase == "back"
2881 || anArgCase == "-b"
2882 || anArgCase == "b")
2883 {
2884 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Back : V3d_TypeOfOrientation_Zup_Back, isYup);
2885 }
2886 else if (anArgCase == "-top"
2887 || anArgCase == "top"
2888 || anArgCase == "-t"
2889 || anArgCase == "t")
2890 {
2891 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Top : V3d_TypeOfOrientation_Zup_Top, isYup);
2892 }
2893 else if (anArgCase == "-bottom"
2894 || anArgCase == "bottom"
2895 || anArgCase == "-bot"
2896 || anArgCase == "bot"
2897 || anArgCase == "-b"
2898 || anArgCase == "b")
2899 {
2900 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Bottom : V3d_TypeOfOrientation_Zup_Bottom, isYup);
2901 }
2902 else if (anArgCase == "-left"
2903 || anArgCase == "left"
2904 || anArgCase == "-l"
2905 || anArgCase == "l")
2906 {
2907 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Left : V3d_TypeOfOrientation_Zup_Left, isYup);
2908 }
2909 else if (anArgCase == "-right"
2910 || anArgCase == "right"
2911 || anArgCase == "-r"
2912 || anArgCase == "r")
2913 {
2914 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_Right : V3d_TypeOfOrientation_Zup_Right, isYup);
2915 }
2916 else if (anArgCase == "-axoleft"
2917 || anArgCase == "-leftaxo"
2918 || anArgCase == "axoleft"
2919 || anArgCase == "leftaxo")
2920 {
2921 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoLeft : V3d_TypeOfOrientation_Zup_AxoLeft, isYup);
2922 }
2923 else if (anArgCase == "-axo"
2924 || anArgCase == "axo"
2925 || anArgCase == "-a"
2926 || anArgCase == "a"
2927 || anArgCase == "-axoright"
2928 || anArgCase == "-rightaxo"
2929 || anArgCase == "axoright"
2930 || anArgCase == "rightaxo")
2931 {
2932 aView->SetProj (isYup ? V3d_TypeOfOrientation_Yup_AxoRight : V3d_TypeOfOrientation_Zup_AxoRight, isYup);
2933 }
2934 else if (anArgCase == "+x")
2935 {
2936 aView->SetProj (V3d_Xpos, isYup);
2937 }
2938 else if (anArgCase == "-x")
2939 {
2940 aView->SetProj (V3d_Xneg, isYup);
2941 }
2942 else if (anArgCase == "+y")
2943 {
2944 aView->SetProj (V3d_Ypos, isYup);
2945 }
2946 else if (anArgCase == "-y")
2947 {
2948 aView->SetProj (V3d_Yneg, isYup);
2949 }
2950 else if (anArgCase == "+z")
2951 {
2952 aView->SetProj (V3d_Zpos, isYup);
2953 }
2954 else if (anArgCase == "-z")
2955 {
2956 aView->SetProj (V3d_Zneg, isYup);
2957 }
2958 else if (anArgCase == "+x+y+z")
2959 {
2960 aView->SetProj (V3d_XposYposZpos, isYup);
2961 }
2962 else if (anArgCase == "+x+y-z")
2963 {
2964 aView->SetProj (V3d_XposYposZneg, isYup);
2965 }
2966 else if (anArgCase == "+x-y+z")
2967 {
2968 aView->SetProj (V3d_XposYnegZpos, isYup);
2969 }
2970 else if (anArgCase == "+x-y-z")
2971 {
2972 aView->SetProj (V3d_XposYnegZneg, isYup);
2973 }
2974 else if (anArgCase == "-x+y+z")
2975 {
2976 aView->SetProj (V3d_XnegYposZpos, isYup);
2977 }
2978 else if (anArgCase == "-x+y-z")
2979 {
2980 aView->SetProj (V3d_XnegYposZneg, isYup);
2981 }
2982 else if (anArgCase == "-x-y+z")
2983 {
2984 aView->SetProj (V3d_XnegYnegZpos, isYup);
2985 }
2986 else if (anArgCase == "-x-y-z")
2987 {
2988 aView->SetProj (V3d_XnegYnegZneg, isYup);
2989 }
2990 else if (anArgCase == "+x+y")
2991 {
2992 aView->SetProj (V3d_XposYpos, isYup);
2993 }
2994 else if (anArgCase == "+x-y")
2995 {
2996 aView->SetProj (V3d_XposYneg, isYup);
2997 }
2998 else if (anArgCase == "-x+y")
2999 {
3000 aView->SetProj (V3d_XnegYpos, isYup);
3001 }
3002 else if (anArgCase == "-x-y")
3003 {
3004 aView->SetProj (V3d_XnegYneg, isYup);
3005 }
3006 else if (anArgCase == "+x+z")
3007 {
3008 aView->SetProj (V3d_XposZpos, isYup);
3009 }
3010 else if (anArgCase == "+x-z")
3011 {
3012 aView->SetProj (V3d_XposZneg, isYup);
3013 }
3014 else if (anArgCase == "-x+z")
3015 {
3016 aView->SetProj (V3d_XnegZpos, isYup);
3017 }
3018 else if (anArgCase == "-x-z")
3019 {
3020 aView->SetProj (V3d_XnegZneg, isYup);
3021 }
3022 else if (anArgCase == "+y+z")
3023 {
3024 aView->SetProj (V3d_YposZpos, isYup);
3025 }
3026 else if (anArgCase == "+y-z")
3027 {
3028 aView->SetProj (V3d_YposZneg, isYup);
3029 }
3030 else if (anArgCase == "-y+z")
3031 {
3032 aView->SetProj (V3d_YnegZpos, isYup);
3033 }
3034 else if (anArgCase == "-y-z")
3035 {
3036 aView->SetProj (V3d_YnegZneg, isYup);
3037 }
3038 else if (anArgIter + 1 < theNbArgs
3039 && anArgCase == "-frame"
3040 && TCollection_AsciiString (theArgVec[anArgIter + 1]).Length() == 4)
3041 {
3042 TCollection_AsciiString aFrameDef (theArgVec[++anArgIter]);
3043 aFrameDef.LowerCase();
3044 gp_Dir aRight, anUp;
3045 if (aFrameDef.Value (2) == aFrameDef.Value (4))
3046 {
3047 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3048 return 1;
3049 }
44b8f2d6 3050
fc552d84 3051 if (aFrameDef.Value (2) == 'x')
3052 {
3053 aRight = aFrameDef.Value (1) == '+' ? gp::DX() : -gp::DX();
3054 }
3055 else if (aFrameDef.Value (2) == 'y')
3056 {
3057 aRight = aFrameDef.Value (1) == '+' ? gp::DY() : -gp::DY();
3058 }
3059 else if (aFrameDef.Value (2) == 'z')
3060 {
3061 aRight = aFrameDef.Value (1) == '+' ? gp::DZ() : -gp::DZ();
3062 }
3063 else
3064 {
3065 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3066 return 1;
3067 }
7fd59977 3068
fc552d84 3069 if (aFrameDef.Value (4) == 'x')
3070 {
3071 anUp = aFrameDef.Value (3) == '+' ? gp::DX() : -gp::DX();
3072 }
3073 else if (aFrameDef.Value (4) == 'y')
3074 {
3075 anUp = aFrameDef.Value (3) == '+' ? gp::DY() : -gp::DY();
3076 }
3077 else if (aFrameDef.Value (4) == 'z')
3078 {
3079 anUp = aFrameDef.Value (3) == '+' ? gp::DZ() : -gp::DZ();
3080 }
3081 else
3082 {
3083 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3084 return 1;
3085 }
44b8f2d6 3086
fc552d84 3087 const Handle(Graphic3d_Camera)& aCamera = aView->Camera();
3088 const gp_Pnt anOriginVCS = aCamera->ConvertWorld2View (gp::Origin());
3089 const gp_Dir aDir = anUp.Crossed (aRight);
3090 aCamera->SetCenter (gp_Pnt (0, 0, 0));
3091 aCamera->SetDirection (aDir);
3092 aCamera->SetUp (anUp);
3093 aCamera->OrthogonalizeUp();
44b8f2d6 3094
fc552d84 3095 aView->Panning (anOriginVCS.X(), anOriginVCS.Y());
3096 aView->Update();
3097 }
3098 else
3099 {
3100 std::cout << "Syntax error at '" << theArgVec[anArgIter] << "'\n";
3101 return 1;
3102 }
3103 }
3104 }
44b8f2d6 3105
fc552d84 3106 if (!isGeneralCmd
3107 && theNbArgs != 1)
3108 {
3109 std::cout << "Syntax error: wrong number of arguments\n";
3110 return 1;
3111 }
3112 return 0;
7fd59977 3113}
3114
3115//==============================================================================
3116//function : VHelp
3117//purpose : Dsiplay help on viewer Keyboead and mouse commands
3118//Draw arg : No args
3119//==============================================================================
3120
3121static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
3122{
586db386 3123 di << "=========================\n";
3124 di << "F : FitAll\n";
3125 di << "T : TopView\n";
3126 di << "B : BottomView\n";
3127 di << "R : RightView\n";
3128 di << "L : LeftView\n";
3129 di << "A : AxonometricView\n";
3130 di << "D : ResetView\n";
3131
3132 di << "=========================\n";
3133 di << "S : Shading\n";
3134 di << "W : Wireframe\n";
49582f9d 3135 di << "H : HiddenLineRemoval\n";
586db386 3136 di << "U : Unset display mode\n";
3137 di << "Delete : Remove selection from viewer\n";
3138
3139 di << "=========================\n";
3140 di << "Selection mode \n";
3141 di << "0 : Shape\n";
3142 di << "1 : Vertex\n";
3143 di << "2 : Edge\n";
3144 di << "3 : Wire\n";
3145 di << "4 : Face\n";
3146 di << "5 : Shell\n";
3147 di << "6 : Solid\n";
3148 di << "7 : Compound\n";
3149
3150 di << "=========================\n";
49582f9d 3151 di << "< : Hilight next detected\n";
3152 di << "> : Hilight previous detected\n";
7fd59977 3153
3154 return 0;
3155}
3156
57c28b61 3157#ifdef _WIN32
7fd59977 3158
49582f9d 3159static LRESULT WINAPI AdvViewerWindowProc (HWND theWinHandle,
3160 UINT theMsg,
3161 WPARAM wParam,
3162 LPARAM lParam )
7fd59977 3163{
49582f9d 3164 if (ViewerTest_myViews.IsEmpty())
3165 {
3166 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
3167 }
7fd59977 3168
49582f9d 3169 switch (theMsg)
3170 {
18d715bd 3171 case WM_CLOSE:
49582f9d 3172 {
3173 // Delete view from map of views
3174 ViewerTest::RemoveView (FindViewIdByWindowHandle (theWinHandle));
3175 return 0;
3176 }
18d715bd 3177 case WM_ACTIVATE:
49582f9d 3178 {
3179 if (LOWORD(wParam) == WA_CLICKACTIVE
3180 || LOWORD(wParam) == WA_ACTIVE
3181 || ViewerTest::CurrentView().IsNull())
18d715bd 3182 {
3183 // Activate inactive window
49582f9d 3184 if (VT_GetWindow().IsNull()
3185 || (HWND )VT_GetWindow()->HWindow() != theWinHandle)
625e1958 3186 {
49582f9d 3187 ActivateView (FindViewIdByWindowHandle (theWinHandle));
625e1958 3188 }
7fd59977 3189 }
7fd59977 3190 break;
49582f9d 3191 }
7fd59977 3192 default:
49582f9d 3193 {
3194 return ViewerWindowProc (theWinHandle, theMsg, wParam, lParam);
7fd59977 3195 }
7fd59977 3196 }
49582f9d 3197 return 0;
7fd59977 3198}
3199
49582f9d 3200static LRESULT WINAPI ViewerWindowProc (HWND theWinHandle,
3201 UINT theMsg,
3202 WPARAM wParam,
3203 LPARAM lParam)
7fd59977 3204{
f978241f 3205 const Handle(V3d_View)& aView = ViewerTest::CurrentView();
3206 if (aView.IsNull())
3207 {
49582f9d 3208 return DefWindowProcW (theWinHandle, theMsg, wParam, lParam);
f978241f 3209 }
7fd59977 3210
49582f9d 3211 switch (theMsg)
3212 {
7fd59977 3213 case WM_PAINT:
49582f9d 3214 {
3215 PAINTSTRUCT aPaint;
3216 BeginPaint(theWinHandle, &aPaint);
3217 EndPaint (theWinHandle, &aPaint);
3218 ViewerTest::CurrentEventManager()->ProcessExpose();
7fd59977 3219 break;
49582f9d 3220 }
7fd59977 3221 case WM_SIZE:
49582f9d 3222 {
3223 ViewerTest::CurrentEventManager()->ProcessConfigure();
7fd59977 3224 break;
49582f9d 3225 }
f978241f 3226 case WM_MOVE:
3227 case WM_MOVING:
3228 case WM_SIZING:
49582f9d 3229 {
f978241f 3230 switch (aView->RenderingParams().StereoMode)
3231 {
3232 case Graphic3d_StereoMode_RowInterlaced:
3233 case Graphic3d_StereoMode_ColumnInterlaced:
3234 case Graphic3d_StereoMode_ChessBoard:
49582f9d 3235 {
3236 // track window moves to reverse stereo pair
3237 aView->MustBeResized();
3238 aView->Update();
f978241f 3239 break;
49582f9d 3240 }
f978241f 3241 default:
3242 break;
3243 }
3244 break;
49582f9d 3245 }
3246 case WM_KEYUP:
7fd59977 3247 case WM_KEYDOWN:
49582f9d 3248 {
3249 const Aspect_VKey aVKey = WNT_Window::VirtualKeyFromNative ((Standard_Integer )wParam);
3250 if (aVKey != Aspect_VKey_UNKNOWN)
4fe56619 3251 {
49582f9d 3252 const double aTimeStamp = ViewerTest::CurrentEventManager()->EventTime();
3253 if (theMsg == WM_KEYDOWN)
f978241f 3254 {
49582f9d 3255 ViewerTest::CurrentEventManager()->KeyDown (aVKey, aTimeStamp);
f978241f 3256 }
49582f9d 3257 else
f978241f 3258 {
49582f9d 3259 ViewerTest::CurrentEventManager()->KeyUp (aVKey, aTimeStamp);
f978241f 3260 }
49582f9d 3261 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
7fd59977 3262 }
3263 break;
49582f9d 3264 }
7fd59977 3265 case WM_LBUTTONUP:
3266 case WM_MBUTTONUP:
3267 case WM_RBUTTONUP:
7fd59977 3268 case WM_LBUTTONDOWN:
3269 case WM_MBUTTONDOWN:
3270 case WM_RBUTTONDOWN:
49582f9d 3271 {
3272 const Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3273 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3274 Aspect_VKeyMouse aButton = Aspect_VKeyMouse_NONE;
3275 switch (theMsg)
7fd59977 3276 {
49582f9d 3277 case WM_LBUTTONUP:
3278 case WM_LBUTTONDOWN:
3279 aButton = Aspect_VKeyMouse_LeftButton;
3280 break;
3281 case WM_MBUTTONUP:
3282 case WM_MBUTTONDOWN:
3283 aButton = Aspect_VKeyMouse_MiddleButton;
3284 break;
3285 case WM_RBUTTONUP:
3286 case WM_RBUTTONDOWN:
3287 aButton = Aspect_VKeyMouse_RightButton;
3288 break;
7fd59977 3289 }
49582f9d 3290 if (theMsg == WM_LBUTTONDOWN
3291 || theMsg == WM_MBUTTONDOWN
3292 || theMsg == WM_RBUTTONDOWN)
f978241f 3293 {
49582f9d 3294 if (aButton == Aspect_VKeyMouse_LeftButton)
f978241f 3295 {
49582f9d 3296 TheIsAnimating = Standard_False;
f978241f 3297 }
49582f9d 3298
3299 SetFocus (theWinHandle);
3300 SetCapture(theWinHandle);
3301 ViewerTest::CurrentEventManager()->PressMouseButton (aPos, aButton, aFlags, false);
f978241f 3302 }
3303 else
3304 {
49582f9d 3305 ReleaseCapture();
3306 ViewerTest::CurrentEventManager()->ReleaseMouseButton (aPos, aButton, aFlags, false);
f978241f 3307 }
49582f9d 3308 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
f978241f 3309 break;
3310 }
49582f9d 3311 case WM_MOUSEWHEEL:
3312 {
3313 const int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
3314 const Standard_Real aDeltaF = Standard_Real(aDelta) / Standard_Real(WHEEL_DELTA);
3315 const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (wParam);
3316 Graphic3d_Vec2i aPos (int(short(LOWORD(lParam))), int(short(HIWORD(lParam))));
3317 POINT aCursorPnt = { aPos.x(), aPos.y() };
3318 if (ScreenToClient (theWinHandle, &aCursorPnt))
7fd59977 3319 {
49582f9d 3320 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3321 }
7fd59977 3322
49582f9d 3323 ViewerTest::CurrentEventManager()->UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags));
3324 ViewerTest::CurrentEventManager()->FlushViewEvents (ViewerTest::GetAISContext(), ViewerTest::CurrentView(), true);
3325 break;
3326 }
3327 case WM_MOUSEMOVE:
3328 {
3329 Graphic3d_Vec2i aPos (LOWORD(lParam), HIWORD(lParam));
3330 Aspect_VKeyMouse aButtons = WNT_Window::MouseButtonsFromEvent (wParam);
3331 Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent(wParam);
7fd59977 3332
49582f9d 3333 // don't make a slide-show from input events - fetch the actual mouse cursor position
3334 CURSORINFO aCursor;
3335 aCursor.cbSize = sizeof(aCursor);
3336 if (::GetCursorInfo (&aCursor) != FALSE)
3337 {
3338 POINT aCursorPnt = { aCursor.ptScreenPos.x, aCursor.ptScreenPos.y };
3339 if (ScreenToClient (theWinHandle, &aCursorPnt))
3340 {
3341 // as we override mouse position, we need overriding also mouse state
3342 aPos.SetValues (aCursorPnt.x, aCursorPnt.y);
3343 aButtons = WNT_Window::MouseButtonsAsync();
3344 aFlags = WNT_Window::MouseKeyFlagsAsync();
3345 }
3346 }