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