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