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