0027039: Draw Harness, ViewerTest - Fix rubber-band blinking
[occt.git] / src / ViewerTest / ViewerTest_ViewerCommands.cxx
1 // Created on: 1998-09-01
2 // Created by: Robert COUBLANC
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17 #include <OpenGl_GlCore20.hxx>
18 #include <AIS_ColorScale.hxx>
19 #include <AIS_RubberBand.hxx>
20 #include <AIS_Shape.hxx>
21 #include <AIS_InteractiveObject.hxx>
22 #include <AIS_ListOfInteractive.hxx>
23 #include <AIS_ListIteratorOfListOfInteractive.hxx>
24 #include <DBRep.hxx>
25 #include <Graphic3d_ArrayOfPolylines.hxx>
26 #include <Graphic3d_AspectMarker3d.hxx>
27 #include <Graphic3d_ExportFormat.hxx>
28 #include <Graphic3d_NameOfTextureEnv.hxx>
29 #include <Graphic3d_GraduatedTrihedron.hxx>
30 #include <Graphic3d_TextureEnv.hxx>
31 #include <Graphic3d_TextureParams.hxx>
32 #include <Graphic3d_TypeOfTextureFilter.hxx>
33 #include <Graphic3d_AspectFillArea3d.hxx>
34 #include <ViewerTest.hxx>
35 #include <ViewerTest_AutoUpdater.hxx>
36 #include <ViewerTest_EventManager.hxx>
37 #include <ViewerTest_DoubleMapOfInteractiveAndName.hxx>
38 #include <ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName.hxx>
39 #include <V3d_AmbientLight.hxx>
40 #include <V3d_DirectionalLight.hxx>
41 #include <V3d_PositionalLight.hxx>
42 #include <V3d_SpotLight.hxx>
43 #include <NCollection_DoubleMap.hxx>
44 #include <NCollection_List.hxx>
45 #include <NCollection_Vector.hxx>
46 #include <AIS_InteractiveContext.hxx>
47 #include <Draw_Interpretor.hxx>
48 #include <Draw.hxx>
49 #include <Draw_Appli.hxx>
50 #include <Aspect_PrintAlgo.hxx>
51 #include <Image_AlienPixMap.hxx>
52 #include <OpenGl_GraphicDriver.hxx>
53 #include <OSD_Timer.hxx>
54 #include <TColStd_HSequenceOfAsciiString.hxx>
55 #include <TColStd_SequenceOfInteger.hxx>
56 #include <TColStd_HSequenceOfReal.hxx>
57 #include <TColgp_Array1OfPnt2d.hxx>
58 #include <TColStd_MapOfAsciiString.hxx>
59 #include <Aspect_TypeOfLine.hxx>
60 #include <Image_Diff.hxx>
61 #include <Aspect_DisplayConnection.hxx>
62 #include <gp_Pnt.hxx>
63 #include <gp_Dir.hxx>
64 #include <gp_Pln.hxx>
65 #include <PrsMgr_PresentableObject.hxx>
66 #include <Graphic3d_ClipPlane.hxx>
67 #include <NCollection_DataMap.hxx>
68 #include <Graphic3d_Texture2Dmanual.hxx>
69 #include <Prs3d_ShadingAspect.hxx>
70 #include <Prs3d_Drawer.hxx>
71 #include <Prs3d_LineAspect.hxx>
72 #include <Prs3d_Root.hxx>
73
74 #ifdef _WIN32
75 #undef DrawText
76 #endif
77
78 #include <cstdlib>
79
80 #if defined(_WIN32)
81   #include <WNT_WClass.hxx>
82   #include <WNT_Window.hxx>
83
84   #if defined(_MSC_VER)
85     #define _CRT_SECURE_NO_DEPRECATE
86     #pragma warning (disable:4996)
87   #endif
88 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
89   #include <Cocoa_Window.hxx>
90 #else
91   #include <Xw_Window.hxx>
92   #include <X11/Xlib.h> /* contains some dangerous #defines such as Status, True etc. */
93   #include <X11/Xutil.h>
94   #include <tk.h>
95 #endif
96
97 // Auxiliary definitions
98 static const char THE_KEY_DELETE = 127;
99
100 //==============================================================================
101 //  VIEWER GLOBAL VARIABLES
102 //==============================================================================
103
104 Standard_IMPORT Standard_Boolean Draw_VirtualWindows;
105 Standard_IMPORT Standard_Boolean Draw_Interprete (const char* theCommand);
106
107 Standard_EXPORT int ViewerMainLoop(Standard_Integer , const char** argv);
108 extern ViewerTest_DoubleMapOfInteractiveAndName& GetMapOfAIS();
109
110 extern int VErase (Draw_Interpretor& theDI,
111                    Standard_Integer  theArgNb,
112                    const char**      theArgVec);
113
114 #if defined(_WIN32)
115 static Handle(WNT_Window)& VT_GetWindow() {
116   static Handle(WNT_Window) WNTWin;
117   return WNTWin;
118 }
119 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
120 static Handle(Cocoa_Window)& VT_GetWindow()
121 {
122   static Handle(Cocoa_Window) aWindow;
123   return aWindow;
124 }
125 extern void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow);
126 extern void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle);
127 extern void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight);
128
129 #else
130 static Handle(Xw_Window)& VT_GetWindow(){
131   static Handle(Xw_Window) XWWin;
132   return XWWin;
133 }
134
135 static void VProcessEvents(ClientData,int);
136 #endif
137
138 static Handle(Aspect_DisplayConnection)& GetDisplayConnection()
139 {
140   static Handle(Aspect_DisplayConnection) aDisplayConnection;
141   return aDisplayConnection;
142 }
143
144 static void SetDisplayConnection (const Handle(Aspect_DisplayConnection)& theDisplayConnection)
145 {
146   GetDisplayConnection() = theDisplayConnection;
147 }
148
149 #if defined(_WIN32) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
150 Aspect_Handle GetWindowHandle(const Handle(Aspect_Window)& theWindow)
151 {
152   Aspect_Handle aWindowHandle = (Aspect_Handle)NULL;
153 #if defined(_WIN32)
154   const Handle (WNT_Window) aWindow = Handle(WNT_Window)::DownCast (theWindow);
155   if (!aWindow.IsNull())
156     return aWindow->HWindow();
157 #elif (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
158   const Handle (Xw_Window) aWindow = Handle(Xw_Window)::DownCast (theWindow);
159   if (!aWindow.IsNull())
160   return aWindow->XWindow();
161 #endif
162   return aWindowHandle;
163 }
164 #endif
165
166 static Standard_Boolean MyHLRIsOn = Standard_False;
167
168 NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews;
169 static NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>  ViewerTest_myContexts;
170 static NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)> ViewerTest_myDrivers;
171 static OpenGl_Caps ViewerTest_myDefaultCaps;
172
173 #define ZCLIPWIDTH 1.
174
175 static void OSWindowSetup();
176
177 static struct
178 {
179   Quantity_Color FlatColor;
180   Quantity_Color GradientColor1;
181   Quantity_Color GradientColor2;
182   Aspect_GradientFillMethod FillMethod;
183 } ViewerTest_DefaultBackground = { Quantity_NOC_BLACK, Quantity_NOC_BLACK, Quantity_NOC_BLACK, Aspect_GFM_NONE };
184
185 //==============================================================================
186 //  EVENT GLOBAL VARIABLES
187 //==============================================================================
188
189 static int Start_Rot = 0;
190 static int ZClipIsOn = 0;
191 int X_Motion = 0; // Current cursor position
192 int Y_Motion = 0;
193 int X_ButtonPress = 0; // Last ButtonPress position
194 int Y_ButtonPress = 0;
195 Standard_Boolean IsDragged = Standard_False;
196 Standard_Boolean DragFirst = Standard_False;
197
198
199 Standard_EXPORT const Handle(AIS_RubberBand)& GetRubberBand()
200 {
201   static Handle(AIS_RubberBand) aBand;
202   if (aBand.IsNull())
203   {
204     aBand = new AIS_RubberBand (Quantity_NOC_LIGHTBLUE, Aspect_TOL_SOLID, Quantity_NOC_LIGHTBLUE, 0.4, 1.0);
205     aBand->SetDisplayMode (0);
206   }
207   return aBand;
208 }
209
210 //==============================================================================
211
212 #ifdef _WIN32
213 static LRESULT WINAPI ViewerWindowProc(
214                                        HWND hwnd,
215                                        UINT uMsg,
216                                        WPARAM wParam,
217                                        LPARAM lParam );
218 static LRESULT WINAPI AdvViewerWindowProc(
219   HWND hwnd,
220   UINT uMsg,
221   WPARAM wParam,
222   LPARAM lParam );
223 #endif
224
225
226 //==============================================================================
227 //function : WClass
228 //purpose  :
229 //==============================================================================
230
231 const Handle(MMgt_TShared)& ViewerTest::WClass()
232 {
233   static Handle(MMgt_TShared) theWClass;
234 #if defined(_WIN32)
235   if (theWClass.IsNull())
236   {
237     theWClass = new WNT_WClass ("GW3D_Class", AdvViewerWindowProc,
238       CS_VREDRAW | CS_HREDRAW, 0, 0,
239       ::LoadCursor (NULL, IDC_ARROW));
240   }
241 #endif
242   return theWClass;
243 }
244
245 //==============================================================================
246 //function : CreateName
247 //purpose  : Create numerical name for new object in theMap
248 //==============================================================================
249 template <typename ObjectType>
250 TCollection_AsciiString CreateName (const NCollection_DoubleMap <TCollection_AsciiString, ObjectType>& theObjectMap,
251                                     const TCollection_AsciiString& theDefaultString)
252 {
253   if (theObjectMap.IsEmpty())
254     return theDefaultString + TCollection_AsciiString(1);
255
256   Standard_Integer aNextKey = 1;
257   Standard_Boolean isFound = Standard_False;
258   while (!isFound)
259   {
260     TCollection_AsciiString aStringKey = theDefaultString + TCollection_AsciiString(aNextKey);
261     // Look for objects with default names
262     if (theObjectMap.IsBound1(aStringKey))
263     {
264       aNextKey++;
265     }
266     else
267       isFound = Standard_True;
268   }
269
270   return theDefaultString + TCollection_AsciiString(aNextKey);
271 }
272
273 //==============================================================================
274 //structure : ViewerTest_Names
275 //purpose   : Allow to operate with full view name: driverName/viewerName/viewName
276 //==============================================================================
277 struct ViewerTest_Names
278 {
279 private:
280   TCollection_AsciiString myDriverName;
281   TCollection_AsciiString myViewerName;
282   TCollection_AsciiString myViewName;
283
284 public:
285
286   const TCollection_AsciiString& GetDriverName () const
287   {
288     return myDriverName;
289   }
290   void SetDriverName (const TCollection_AsciiString& theDriverName)
291   {
292     myDriverName = theDriverName;
293   }
294   const TCollection_AsciiString& GetViewerName () const
295   {
296     return myViewerName;
297   }
298   void SetViewerName (const TCollection_AsciiString& theViewerName)
299   {
300     myViewerName = theViewerName;
301   }
302   const TCollection_AsciiString& GetViewName () const
303   {
304     return myViewName;
305   }
306   void SetViewName (const TCollection_AsciiString& theViewName)
307   {
308     myViewName = theViewName;
309   }
310
311   //===========================================================================
312   //function : Constructor for ViewerTest_Names
313   //purpose  : Get view, viewer, driver names from custom string
314   //===========================================================================
315
316   ViewerTest_Names (const TCollection_AsciiString& theInputString)
317   {
318     TCollection_AsciiString aName(theInputString);
319     if (theInputString.IsEmpty())
320     {
321       // Get current configuration
322       if (ViewerTest_myDrivers.IsEmpty())
323         myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
324           (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
325       else
326         myDriverName = ViewerTest_myDrivers.Find2
327         (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
328
329       if(ViewerTest_myContexts.IsEmpty())
330       {
331         myViewerName = CreateName <Handle(AIS_InteractiveContext)>
332           (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
333       }
334       else
335         myViewerName = ViewerTest_myContexts.Find2 (ViewerTest::GetAISContext());
336
337         myViewName = CreateName <Handle(V3d_View)>
338           (ViewerTest_myViews, TCollection_AsciiString(myViewerName + "/View"));
339     }
340     else
341     {
342       // There is at least view name
343       Standard_Integer aParserNumber = 0;
344       for (Standard_Integer i = 0; i < 3; ++i)
345       {
346         Standard_Integer aParserPos = aName.SearchFromEnd("/");
347         if(aParserPos != -1)
348         {
349           aParserNumber++;
350           aName.Split(aParserPos-1);
351         }
352         else
353           break;
354       }
355       if (aParserNumber == 0)
356       {
357         // Only view name
358         if (!ViewerTest::GetAISContext().IsNull())
359         {
360           myDriverName = ViewerTest_myDrivers.Find2
361           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
362           myViewerName = ViewerTest_myContexts.Find2
363           (ViewerTest::GetAISContext());
364         }
365         else
366         {
367           // There is no opened contexts here, need to create names for viewer and driver
368           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
369             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
370
371           myViewerName = CreateName <Handle(AIS_InteractiveContext)>
372             (ViewerTest_myContexts, TCollection_AsciiString (myDriverName + "/Viewer"));
373         }
374         myViewName = TCollection_AsciiString(myViewerName + "/" + theInputString);
375       }
376       else if (aParserNumber == 1)
377       {
378         // Here is viewerName/viewName
379         if (!ViewerTest::GetAISContext().IsNull())
380           myDriverName = ViewerTest_myDrivers.Find2
381           (ViewerTest::GetAISContext()->CurrentViewer()->Driver());
382         else
383         {
384           // There is no opened contexts here, need to create name for driver
385           myDriverName = CreateName<Handle(Graphic3d_GraphicDriver)>
386             (ViewerTest_myDrivers, TCollection_AsciiString("Driver"));
387         }
388         myViewerName = TCollection_AsciiString(myDriverName + "/" + aName);
389
390         myViewName = TCollection_AsciiString(myDriverName + "/" + theInputString);
391       }
392       else
393       {
394         //Here is driverName/viewerName/viewName
395         myDriverName = TCollection_AsciiString(aName);
396
397         TCollection_AsciiString aViewerName(theInputString);
398         aViewerName.Split(aViewerName.SearchFromEnd("/") - 1);
399         myViewerName = TCollection_AsciiString(aViewerName);
400
401         myViewName = TCollection_AsciiString(theInputString);
402       }
403     }
404   }
405 };
406
407 //==============================================================================
408 //function : FindContextByView
409 //purpose  : Find AIS_InteractiveContext by View
410 //==============================================================================
411
412 Handle(AIS_InteractiveContext) FindContextByView (const Handle(V3d_View)& theView)
413 {
414   Handle(AIS_InteractiveContext) anAISContext;
415
416   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
417        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
418   {
419     if (anIter.Value()->CurrentViewer() == theView->Viewer())
420        return anIter.Key2();
421   }
422   return anAISContext;
423 }
424
425
426 //==============================================================================
427 //function : SetWindowTitle
428 //purpose  : Set window title
429 //==============================================================================
430
431 void SetWindowTitle (const Handle(Aspect_Window)& theWindow,
432                      Standard_CString theTitle)
433 {
434 #if defined(_WIN32)
435   SetWindowText ((HWND)Handle(WNT_Window)::DownCast(theWindow)->HWindow(),
436     theTitle);
437 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
438   SetCocoaWindowTitle (Handle(Cocoa_Window)::DownCast(theWindow), theTitle);
439 #else
440   if(GetDisplayConnection()->GetDisplay())
441   {
442     Window aWindow =
443       Handle(Xw_Window)::DownCast(theWindow)->XWindow();
444     XStoreName (GetDisplayConnection()->GetDisplay(), aWindow , theTitle);
445   }
446 #endif
447 }
448
449 //==============================================================================
450 //function : IsWindowOverlapped
451 //purpose  : Check if theWindow overlapp another view
452 //==============================================================================
453
454 Standard_Boolean IsWindowOverlapped (const Standard_Integer thePxLeft,
455                                      const Standard_Integer thePxTop,
456                                      const Standard_Integer thePxRight,
457                                      const Standard_Integer thePxBottom,
458                                      TCollection_AsciiString& theViewId)
459 {
460   for(NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
461       anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
462   {
463     Standard_Integer aTop = 0,
464       aLeft = 0,
465       aRight = 0,
466       aBottom = 0;
467     anIter.Value()->Window()->Position(aLeft, aTop, aRight, aBottom);
468     if ((thePxLeft >= aLeft && thePxLeft <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
469         (thePxLeft >= aLeft && thePxLeft <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom) ||
470         (thePxRight >= aLeft && thePxRight <= aRight && thePxTop >= aTop && thePxTop <= aBottom) ||
471         (thePxRight >= aLeft && thePxRight <= aRight && thePxBottom >= aTop && thePxBottom <= aBottom))
472     {
473       theViewId = anIter.Key1();
474       return Standard_True;
475     }
476   }
477   return Standard_False;
478 }
479
480 // Workaround: to create and delete non-orthographic views outside ViewerTest
481 void ViewerTest::RemoveViewName (const TCollection_AsciiString& theName)
482 {
483   ViewerTest_myViews.UnBind1 (theName);
484 }
485
486 void ViewerTest::InitViewName (const TCollection_AsciiString& theName,
487                                const Handle(V3d_View)& theView)
488 {
489   ViewerTest_myViews.Bind (theName, theView);
490 }
491
492 TCollection_AsciiString ViewerTest::GetCurrentViewName ()
493 {
494   return ViewerTest_myViews.Find2( ViewerTest::CurrentView());
495 }
496 //==============================================================================
497 //function : ViewerInit
498 //purpose  : Create the window viewer and initialize all the global variable
499 //==============================================================================
500
501 TCollection_AsciiString ViewerTest::ViewerInit (const Standard_Integer thePxLeft,
502                                                 const Standard_Integer thePxTop,
503                                                 const Standard_Integer thePxWidth,
504                                                 const Standard_Integer thePxHeight,
505                                                 Standard_CString theViewName,
506                                                 Standard_CString theDisplayName)
507 {
508   // Default position and dimension of the viewer window.
509   // Note that left top corner is set to be sufficiently small to have
510   // window fit in the small screens (actual for remote desktops, see #23003).
511   // The position corresponds to the window's client area, thus some
512   // gap is added for window frame to be visible.
513   Standard_Integer aPxLeft   = 20;
514   Standard_Integer aPxTop    = 40;
515   Standard_Integer aPxWidth  = 409;
516   Standard_Integer aPxHeight = 409;
517   Standard_Boolean toCreateViewer = Standard_False;
518
519   Handle(OpenGl_GraphicDriver) aGraphicDriver;
520   ViewerTest_Names aViewNames(theViewName);
521   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName ()))
522     aViewNames.SetViewName (aViewNames.GetViewerName() + "/" + CreateName<Handle(V3d_View)>(ViewerTest_myViews, "View"));
523
524   if (thePxLeft != 0)
525     aPxLeft = thePxLeft;
526   if (thePxTop != 0)
527     aPxTop = thePxTop;
528   if (thePxWidth != 0)
529     aPxWidth = thePxWidth;
530   if (thePxHeight != 0)
531     aPxHeight = thePxHeight;
532
533   // Get graphic driver (create it or get from another view)
534   if (!ViewerTest_myDrivers.IsBound1 (aViewNames.GetDriverName()))
535   {
536     // Get connection string
537   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
538     TCollection_AsciiString aDisplayName(theDisplayName);
539     if (!aDisplayName.IsEmpty())
540       SetDisplayConnection (new Aspect_DisplayConnection ());
541     else
542       SetDisplayConnection (new Aspect_DisplayConnection (aDisplayName));
543   #else
544     (void)theDisplayName; // avoid warning on unused argument
545     SetDisplayConnection (new Aspect_DisplayConnection ());
546   #endif
547     aGraphicDriver = new OpenGl_GraphicDriver (GetDisplayConnection());
548     aGraphicDriver->ChangeOptions() = ViewerTest_myDefaultCaps;
549     ViewerTest_myDrivers.Bind (aViewNames.GetDriverName(), aGraphicDriver);
550     toCreateViewer = Standard_True;
551   }
552   else
553   {
554     aGraphicDriver = Handle(OpenGl_GraphicDriver)::DownCast (ViewerTest_myDrivers.Find1 (aViewNames.GetDriverName()));
555   }
556
557   //Dispose the window if input parameters are default
558   if (!ViewerTest_myViews.IsEmpty() && thePxLeft == 0 && thePxTop == 0)
559   {
560     Standard_Integer aTop = 0,
561                      aLeft = 0,
562                      aRight = 0,
563                      aBottom = 0,
564                      aScreenWidth = 0,
565                      aScreenHeight = 0;
566
567     // Get screen resolution
568 #if defined(_WIN32) || defined(__WIN32__)
569     RECT aWindowSize;
570     GetClientRect(GetDesktopWindow(), &aWindowSize);
571     aScreenHeight = aWindowSize.bottom;
572     aScreenWidth = aWindowSize.right;
573 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
574     GetCocoaScreenResolution (aScreenWidth, aScreenHeight);
575 #else
576     Screen *aScreen = DefaultScreenOfDisplay(GetDisplayConnection()->GetDisplay());
577     aScreenWidth = WidthOfScreen(aScreen);
578     aScreenHeight = HeightOfScreen(aScreen);
579 #endif
580
581     TCollection_AsciiString anOverlappedViewId("");
582
583     while (IsWindowOverlapped (aPxLeft, aPxTop, aPxLeft + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId))
584     {
585       ViewerTest_myViews.Find1(anOverlappedViewId)->Window()->Position (aLeft, aTop, aRight, aBottom);
586
587       if (IsWindowOverlapped (aRight + 20, aPxTop, aRight + 20 + aPxWidth, aPxTop + aPxHeight, anOverlappedViewId)
588         && aRight + 2*aPxWidth + 40 > aScreenWidth)
589       {
590         if (aBottom + aPxHeight + 40 > aScreenHeight)
591         {
592           aPxLeft = 20;
593           aPxTop = 40;
594           break;
595         }
596         aPxLeft = 20;
597         aPxTop = aBottom + 40;
598       }
599       else
600         aPxLeft = aRight + 20;
601     }
602   }
603
604   // Get viewer name
605   TCollection_AsciiString aTitle("3D View - ");
606   aTitle = aTitle + aViewNames.GetViewName() + "(*)";
607
608   // Change name of current active window
609   if (!ViewerTest::CurrentView().IsNull())
610   {
611     TCollection_AsciiString anActiveWindowTitle("3D View - ");
612     anActiveWindowTitle = anActiveWindowTitle
613       + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
614     SetWindowTitle (ViewerTest::CurrentView()->Window(), anActiveWindowTitle.ToCString());
615   }
616
617   // Create viewer
618   Handle(V3d_Viewer) a3DViewer;
619   // If it's the single view, we first look for empty context
620   if (ViewerTest_myViews.IsEmpty() && !ViewerTest_myContexts.IsEmpty())
621   {
622     NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
623       anIter(ViewerTest_myContexts);
624     if (anIter.More())
625       ViewerTest::SetAISContext (anIter.Value());
626     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
627   }
628   else if (ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName()))
629   {
630     ViewerTest::SetAISContext(ViewerTest_myContexts.Find1(aViewNames.GetViewerName()));
631     a3DViewer = ViewerTest::GetAISContext()->CurrentViewer();
632   }
633   else if (a3DViewer.IsNull())
634   {
635     toCreateViewer = Standard_True;
636     TCollection_ExtendedString NameOfWindow("Viewer3D");
637     a3DViewer = new V3d_Viewer(aGraphicDriver, NameOfWindow.ToExtString());
638     a3DViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
639     a3DViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
640                                            ViewerTest_DefaultBackground.GradientColor2,
641                                            ViewerTest_DefaultBackground.FillMethod);
642   }
643
644   // AIS context setup
645   if (ViewerTest::GetAISContext().IsNull() ||
646       !(ViewerTest_myContexts.IsBound1(aViewNames.GetViewerName())))
647   {
648     Handle(AIS_InteractiveContext) aContext = new AIS_InteractiveContext (a3DViewer);
649     ViewerTest::SetAISContext (aContext);
650     ViewerTest_myContexts.Bind (aViewNames.GetViewerName(), ViewerTest::GetAISContext());
651   }
652   else
653   {
654     ViewerTest::ResetEventManager();
655   }
656
657   // Create window
658 #if defined(_WIN32)
659   VT_GetWindow() = new WNT_Window (aTitle.ToCString(),
660                                     Handle(WNT_WClass)::DownCast (WClass()),
661                                     Draw_VirtualWindows ? WS_POPUP : WS_OVERLAPPEDWINDOW,
662                                     aPxLeft, aPxTop,
663                                     aPxWidth, aPxHeight,
664                                     Quantity_NOC_BLACK);
665 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
666   VT_GetWindow() = new Cocoa_Window (aTitle.ToCString(),
667                                      aPxLeft, aPxTop,
668                                      aPxWidth, aPxHeight);
669   ViewerTest_SetCocoaEventManagerView (VT_GetWindow());
670 #else
671   VT_GetWindow() = new Xw_Window (aGraphicDriver->GetDisplayConnection(),
672                                   aTitle.ToCString(),
673                                   aPxLeft, aPxTop,
674                                   aPxWidth, aPxHeight);
675 #endif
676   VT_GetWindow()->SetVirtual (Draw_VirtualWindows);
677
678   // View setup
679   Handle(V3d_View) aView = a3DViewer->CreateView();
680   aView->SetWindow (VT_GetWindow());
681   ViewerTest::GetAISContext()->RedrawImmediate (a3DViewer);
682
683   ViewerTest::CurrentView(aView);
684   ViewerTest_myViews.Bind (aViewNames.GetViewName(), aView);
685
686   // Setup for X11 or NT
687   OSWindowSetup();
688
689   // Set parameters for V3d_View and V3d_Viewer
690   const Handle (V3d_View) aV3dView = ViewerTest::CurrentView();
691   aV3dView->SetComputedMode(Standard_False);
692   MyHLRIsOn = aV3dView->ComputedMode();
693   aV3dView->SetZClippingDepth(0.5);
694   aV3dView->SetZClippingWidth(ZCLIPWIDTH/2.);
695
696   a3DViewer->SetDefaultBackgroundColor(Quantity_NOC_BLACK);
697   if (toCreateViewer)
698   {
699     a3DViewer->SetDefaultLights();
700     a3DViewer->SetLightOn();
701   }
702
703   #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
704   #if TCL_MAJOR_VERSION  < 8
705   Tk_CreateFileHandler((void*)XConnectionNumber(GetDisplayConnection()->GetDisplay()),
706       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
707   #else
708   Tk_CreateFileHandler(XConnectionNumber(GetDisplayConnection()->GetDisplay()),
709       TK_READABLE, VProcessEvents, (ClientData) VT_GetWindow()->XWindow() );
710   #endif
711   #endif
712
713   VT_GetWindow()->Map();
714
715   // Set the handle of created view in the event manager
716   ViewerTest::ResetEventManager();
717
718   ViewerTest::CurrentView()->Redraw();
719
720   aView.Nullify();
721   a3DViewer.Nullify();
722
723   return aViewNames.GetViewName();
724 }
725
726 //==============================================================================
727 //function : RedrawAllViews
728 //purpose  : Redraw all created views
729 //==============================================================================
730 void ViewerTest::RedrawAllViews()
731 {
732   NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator aViewIt(ViewerTest_myViews);
733   for (; aViewIt.More(); aViewIt.Next())
734   {
735     const Handle(V3d_View)& aView = aViewIt.Key2();
736     aView->Redraw();
737   }
738 }
739
740 //==============================================================================
741 //function : Vinit
742 //purpose  : Create the window viewer and initialize all the global variable
743 //    Use Tk_CreateFileHandler on UNIX to catch the X11 Viewer event
744 //==============================================================================
745
746 static int VInit (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
747 {
748   if (theArgsNb > 9)
749   {
750     std::cerr << theArgVec[0] << ": incorrect number of command arguments.\n"
751               << "Type help for more information.\n";
752     return 1;
753   }
754
755   TCollection_AsciiString aViewName, aDisplayName;
756   Standard_Integer aPxLeft = 0, aPxTop = 0, aPxWidth = 0, aPxHeight = 0;
757   TCollection_AsciiString aName, aValue;
758   for (Standard_Integer anArgIt = 1; anArgIt < theArgsNb; ++anArgIt)
759   {
760     const TCollection_AsciiString anArg = theArgVec[anArgIt];
761     TCollection_AsciiString anArgCase = anArg;
762     anArgCase.UpperCase();
763     if (ViewerTest::SplitParameter (anArg, aName, aValue))
764     {
765       aName.UpperCase();
766       if (aName.IsEqual ("NAME"))
767       {
768         aViewName = aValue;
769       }
770       else if (aName.IsEqual ("L")
771             || aName.IsEqual ("LEFT"))
772       {
773         aPxLeft = aValue.IntegerValue();
774       }
775       else if (aName.IsEqual ("T")
776             || aName.IsEqual ("TOP"))
777       {
778         aPxTop = aValue.IntegerValue();
779       }
780     #if !defined(_WIN32) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
781       else if (aName.IsEqual ("DISP")
782             || aName.IsEqual ("DISPLAY"))
783       {
784         aDisplayName = aValue;
785       }
786     #endif
787       else if (aName.IsEqual ("W")
788             || aName.IsEqual ("WIDTH"))
789       {
790         aPxWidth = aValue.IntegerValue();
791       }
792       else if (aName.IsEqual ("H")
793             || aName.IsEqual ("HEIGHT"))
794       {
795         aPxHeight = aValue.IntegerValue();
796       }
797       else
798       {
799         std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
800       }
801     }
802     else if (aViewName.IsEmpty())
803     {
804       aViewName = anArg;
805     }
806     else
807     {
808       std::cerr << theArgVec[0] << ": Warning: unknown argument " << anArg << ".\n";
809     }
810   }
811
812   ViewerTest_Names aViewNames (aViewName);
813   if (ViewerTest_myViews.IsBound1 (aViewNames.GetViewName()))
814   {
815     TCollection_AsciiString aCommand = TCollection_AsciiString ("vactivate ") + aViewNames.GetViewName();
816     theDi.Eval (aCommand.ToCString());
817     return 0;
818   }
819
820   TCollection_AsciiString aViewId = ViewerTest::ViewerInit (aPxLeft, aPxTop, aPxWidth, aPxHeight,
821                                                             aViewName.ToCString(),
822                                                             aDisplayName.ToCString());
823   theDi << aViewId;
824   return 0;
825 }
826
827 //==============================================================================
828 //function : VHLR
829 //purpose  : hidden lines removal algorithm
830 //draw args: vhlr is_enabled={on|off} [show_hidden={1|0}]
831 //==============================================================================
832
833 static int VHLR (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
834 {
835   if (ViewerTest::CurrentView().IsNull())
836   {
837     di << argv[0] << ": Call vinit before this command, please.\n";
838     return 1;
839   }
840
841   if (argc < 2)
842   {
843     di << argv[0] << ": Wrong number of command arguments.\n"
844       << "Type help " << argv[0] << " for more information.\n";
845     return 1;
846   }
847
848   // Enable or disable HLR mode.
849   Standard_Boolean isHLROn =
850     (!strcasecmp (argv[1], "on")) ? Standard_True : Standard_False;
851
852   if (isHLROn != MyHLRIsOn)
853   {
854     MyHLRIsOn = isHLROn;
855     ViewerTest::CurrentView()->SetComputedMode (MyHLRIsOn);
856   }
857
858   // Show or hide hidden lines in HLR mode.
859   Standard_Boolean isCurrentShowHidden
860     = ViewerTest::GetAISContext()->DefaultDrawer()->DrawHiddenLine();
861
862   Standard_Boolean isShowHidden =
863     (argc == 3) ? (atoi(argv[2]) == 1 ? Standard_True : Standard_False)
864                 : isCurrentShowHidden;
865
866
867   if (isShowHidden != isCurrentShowHidden)
868   {
869     if (isShowHidden)
870     {
871       ViewerTest::GetAISContext()->DefaultDrawer()->EnableDrawHiddenLine();
872     }
873     else
874     {
875       ViewerTest::GetAISContext()->DefaultDrawer()->DisableDrawHiddenLine();
876     }
877
878     // Redisplay shapes.
879     if (MyHLRIsOn)
880     {
881       AIS_ListOfInteractive aListOfShapes;
882       ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
883
884       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes); anIter.More(); anIter.Next())
885       {
886         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast (anIter.Value());
887         if (aShape.IsNull())
888         {
889           continue;
890         }
891         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
892       }
893     }
894   }
895
896   ViewerTest::CurrentView()->Update();
897   return 0;
898 }
899
900 //==============================================================================
901 //function : VHLRType
902 //purpose  : change type of using HLR algorithm
903 //==============================================================================
904
905 static int VHLRType (Draw_Interpretor& di, Standard_Integer argc, const char** argv)
906 {
907   if (ViewerTest::CurrentView().IsNull())
908   {
909     di << argv[0] << ": Call vinit before this command, please.\n";
910     return 1;
911   }
912
913   if (argc < 2)
914   {
915     di << argv[0] << ": Wrong number of command arguments.\n"
916       << "Type help " << argv[0] << " for more information.\n";
917     return 1;
918   }
919
920   Prs3d_TypeOfHLR aTypeOfHLR =
921     (!strcasecmp (argv[1], "algo")) ? Prs3d_TOH_Algo : Prs3d_TOH_PolyAlgo;
922
923   if (argc == 2)
924   {
925     AIS_ListOfInteractive aListOfShapes;
926     ViewerTest::GetAISContext()->DisplayedObjects (aListOfShapes);
927     ViewerTest::GetAISContext()->DefaultDrawer()->SetTypeOfHLR(aTypeOfHLR);
928     for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
929       anIter.More(); anIter.Next())
930     {
931       Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
932       if (aShape.IsNull())
933         continue;
934       if (aShape->TypeOfHLR() != aTypeOfHLR)
935         aShape->SetTypeOfHLR (aTypeOfHLR);
936       if (MyHLRIsOn)
937         ViewerTest::GetAISContext()->Redisplay (aShape, Standard_False);
938     }
939     ViewerTest::CurrentView()->Update();
940     return 0;
941   }
942   else
943   {
944     for (Standard_Integer i = 2; i < argc; ++i)
945     {
946       ViewerTest_DoubleMapOfInteractiveAndName& aMap = GetMapOfAIS();
947       TCollection_AsciiString aName (argv[i]);
948
949       if (!aMap.IsBound2 (aName))
950       {
951         di << argv[0] << ": Wrong shape name:" << aName.ToCString() << ".\n";
952         continue;
953       }
954       Handle(AIS_Shape) anAISObject =
955         Handle(AIS_Shape)::DownCast (aMap.Find2(aName));
956       if (anAISObject.IsNull())
957         continue;
958       anAISObject->SetTypeOfHLR (aTypeOfHLR);
959       if (MyHLRIsOn)
960         ViewerTest::GetAISContext()->Redisplay (anAISObject, Standard_False);
961     }
962     ViewerTest::CurrentView()->Update();
963   }
964
965   return 0;
966 }
967
968 //==============================================================================
969 //function : FindViewIdByWindowHandle
970 //purpose  : Find theView Id in the map of views by window handle
971 //==============================================================================
972 #if defined(_WIN32) || defined(__WIN32__) || (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
973 TCollection_AsciiString FindViewIdByWindowHandle(const Aspect_Handle theWindowHandle)
974 {
975   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator
976        anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
977   {
978     Aspect_Handle aWindowHandle = GetWindowHandle(anIter.Value()->Window());
979     if (aWindowHandle == theWindowHandle)
980       return anIter.Key1();
981   }
982   return TCollection_AsciiString("");
983 }
984 #endif
985
986 //==============================================================================
987 //function : ActivateView
988 //purpose  : Make the view active
989 //==============================================================================
990
991 void ActivateView (const TCollection_AsciiString& theViewName)
992 {
993   const Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
994   if (!aView.IsNull())
995   {
996     Handle(AIS_InteractiveContext) anAISContext = FindContextByView(aView);
997     if (!anAISContext.IsNull())
998     {
999       if (!ViewerTest::CurrentView().IsNull())
1000       {
1001         TCollection_AsciiString aTitle("3D View - ");
1002         aTitle = aTitle + ViewerTest_myViews.Find2 (ViewerTest::CurrentView());
1003         SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1004       }
1005
1006       ViewerTest::CurrentView (aView);
1007       // Update degenerate mode
1008       MyHLRIsOn = ViewerTest::CurrentView()->ComputedMode();
1009       ViewerTest::SetAISContext (anAISContext);
1010       TCollection_AsciiString aTitle = TCollection_AsciiString("3D View - ");
1011       aTitle = aTitle + theViewName + "(*)";
1012       SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1013 #if defined(_WIN32) || defined(__WIN32__)
1014       VT_GetWindow() = Handle(WNT_Window)::DownCast(ViewerTest::CurrentView()->Window());
1015 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1016       VT_GetWindow() = Handle(Cocoa_Window)::DownCast(ViewerTest::CurrentView()->Window());
1017 #else
1018       VT_GetWindow() = Handle(Xw_Window)::DownCast(ViewerTest::CurrentView()->Window());
1019 #endif
1020       SetDisplayConnection(ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
1021       ViewerTest::CurrentView()->Redraw();
1022     }
1023   }
1024 }
1025
1026 //==============================================================================
1027 //function : RemoveView
1028 //purpose  :
1029 //==============================================================================
1030 void ViewerTest::RemoveView (const Handle(V3d_View)& theView,
1031                              const Standard_Boolean  theToRemoveContext)
1032 {
1033   if (!ViewerTest_myViews.IsBound2 (theView))
1034   {
1035     return;
1036   }
1037
1038   const TCollection_AsciiString aViewName = ViewerTest_myViews.Find2 (theView);
1039   RemoveView (aViewName, theToRemoveContext);
1040 }
1041
1042 //==============================================================================
1043 //function : RemoveView
1044 //purpose  : Close and remove view from display, clear maps if neccessary
1045 //==============================================================================
1046 void ViewerTest::RemoveView (const TCollection_AsciiString& theViewName, const Standard_Boolean isContextRemoved)
1047 {
1048   if (!ViewerTest_myViews.IsBound1(theViewName))
1049   {
1050     cout << "Wrong view name\n";
1051     return;
1052   }
1053
1054   // Activate another view if it's active now
1055   if (ViewerTest_myViews.Find1(theViewName) == ViewerTest::CurrentView())
1056   {
1057     if (ViewerTest_myViews.Extent() > 1)
1058     {
1059       TCollection_AsciiString aNewViewName;
1060       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> :: Iterator
1061            anIter(ViewerTest_myViews); anIter.More(); anIter.Next())
1062         if (anIter.Key1() != theViewName)
1063         {
1064           aNewViewName = anIter.Key1();
1065           break;
1066         }
1067         ActivateView (aNewViewName);
1068     }
1069     else
1070     {
1071       Handle(V3d_View) anEmptyView;
1072 #if defined(_WIN32) || defined(__WIN32__)
1073       Handle(WNT_Window) anEmptyWindow;
1074 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1075       Handle(Cocoa_Window) anEmptyWindow;
1076 #else
1077       Handle(Xw_Window) anEmptyWindow;
1078 #endif
1079       VT_GetWindow() = anEmptyWindow;
1080       ViewerTest::CurrentView (anEmptyView);
1081       if (isContextRemoved)
1082       {
1083         Handle(AIS_InteractiveContext) anEmptyContext;
1084         ViewerTest::SetAISContext(anEmptyContext);
1085       }
1086     }
1087   }
1088
1089   // Delete view
1090   Handle(V3d_View) aView = ViewerTest_myViews.Find1(theViewName);
1091   Handle(AIS_InteractiveContext) aCurrentContext = FindContextByView(aView);
1092
1093   // Remove view resources
1094   ViewerTest_myViews.UnBind1(theViewName);
1095   aView->Remove();
1096
1097 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1098   XFlush (GetDisplayConnection()->GetDisplay());
1099 #endif
1100
1101   // Keep context opened only if the closed view is last to avoid
1102   // unused empty contexts
1103   if (!aCurrentContext.IsNull())
1104   {
1105     // Check if there are more difined views in the viewer
1106     aCurrentContext->CurrentViewer()->InitDefinedViews();
1107     if ((isContextRemoved || ViewerTest_myContexts.Size() != 1) && !aCurrentContext->CurrentViewer()->MoreDefinedViews())
1108     {
1109       // Remove driver if there is no viewers that use it
1110       Standard_Boolean isRemoveDriver = Standard_True;
1111       for(NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1112           anIter(ViewerTest_myContexts); anIter.More(); anIter.Next())
1113       {
1114         if (aCurrentContext != anIter.Key2() &&
1115           aCurrentContext->CurrentViewer()->Driver() == anIter.Value()->CurrentViewer()->Driver())
1116         {
1117           isRemoveDriver = Standard_False;
1118           break;
1119         }
1120       }
1121       if(isRemoveDriver)
1122       {
1123         ViewerTest_myDrivers.UnBind2 (aCurrentContext->CurrentViewer()->Driver());
1124       #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
1125         #if TCL_MAJOR_VERSION  < 8
1126         Tk_DeleteFileHandler((void*)XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1127         #else
1128         Tk_DeleteFileHandler(XConnectionNumber(aCurrentContext->CurrentViewer()->Driver()->GetDisplayConnection()->GetDisplay()));
1129         #endif
1130       #endif
1131       }
1132
1133       ViewerTest_myContexts.UnBind2(aCurrentContext);
1134     }
1135   }
1136   cout << "3D View - " << theViewName << " was deleted.\n";
1137
1138 }
1139
1140 //==============================================================================
1141 //function : VClose
1142 //purpose  : Remove the view defined by its name
1143 //==============================================================================
1144
1145 static int VClose (Draw_Interpretor& /*theDi*/,
1146                    Standard_Integer  theArgsNb,
1147                    const char**      theArgVec)
1148 {
1149   NCollection_List<TCollection_AsciiString> aViewList;
1150   if (theArgsNb > 1)
1151   {
1152     TCollection_AsciiString anArg (theArgVec[1]);
1153     anArg.UpperCase();
1154     if (anArg.IsEqual ("ALL")
1155      || anArg.IsEqual ("*"))
1156     {
1157       for (NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter (ViewerTest_myViews);
1158            anIter.More(); anIter.Next())
1159       {
1160         aViewList.Append (anIter.Key1());
1161       }
1162       if (aViewList.IsEmpty())
1163       {
1164         std::cout << "No view to close\n";
1165         return 0;
1166       }
1167     }
1168     else
1169     {
1170       ViewerTest_Names aViewName (theArgVec[1]);
1171       if (!ViewerTest_myViews.IsBound1 (aViewName.GetViewName()))
1172       {
1173         std::cerr << "The view with name '" << theArgVec[1] << "' does not exist\n";
1174         return 1;
1175       }
1176       aViewList.Append (aViewName.GetViewName());
1177     }
1178   }
1179   else
1180   {
1181     // close active view
1182     if (ViewerTest::CurrentView().IsNull())
1183     {
1184       std::cerr << "No active view!\n";
1185       return 1;
1186     }
1187     aViewList.Append (ViewerTest_myViews.Find2 (ViewerTest::CurrentView()));
1188   }
1189
1190   Standard_Boolean toRemoveContext = (theArgsNb != 3 || Draw::Atoi (theArgVec[2]) != 1);
1191   for (NCollection_List<TCollection_AsciiString>::Iterator anIter(aViewList);
1192        anIter.More(); anIter.Next())
1193   {
1194     ViewerTest::RemoveView (anIter.Value(), toRemoveContext);
1195   }
1196
1197   return 0;
1198 }
1199
1200 //==============================================================================
1201 //function : VActivate
1202 //purpose  : Activate the view defined by its ID
1203 //==============================================================================
1204
1205 static int VActivate (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1206 {
1207   if (theArgsNb > 2)
1208   {
1209     theDi << theArgVec[0] << ": wrong number of command arguments.\n"
1210     << "Usage: " << theArgVec[0] << " ViewID\n";
1211     return 1;
1212   }
1213   if(theArgsNb == 1)
1214   {
1215     theDi.Eval("vviewlist");
1216     return 0;
1217   }
1218
1219   TCollection_AsciiString aNameString(theArgVec[1]);
1220   if ( strcasecmp( aNameString.ToCString(), "NONE" ) == 0 )
1221   {
1222     TCollection_AsciiString aTitle("3D View - ");
1223     aTitle = aTitle + ViewerTest_myViews.Find2(ViewerTest::CurrentView());
1224     SetWindowTitle (ViewerTest::CurrentView()->Window(), aTitle.ToCString());
1225     Handle(V3d_View) anEmptyView;
1226 #if defined(_WIN32) || defined(__WIN32__)
1227     Handle(WNT_Window) anEmptyWindow;
1228 #elif defined(__APPLE__) && !defined(MACOSX_USE_GLX)
1229     Handle(Cocoa_Window) anEmptyWindow;
1230 #else
1231     Handle(Xw_Window) anEmptyWindow;
1232 #endif
1233     VT_GetWindow() = anEmptyWindow;
1234     ViewerTest::CurrentView (anEmptyView);
1235     ViewerTest::ResetEventManager();
1236     theDi << theArgVec[0] << ": all views are inactive\n";
1237     return 0;
1238   }
1239
1240   ViewerTest_Names aViewNames(aNameString);
1241
1242   // Check if this view exists in the viewer with the driver
1243   if (!ViewerTest_myViews.IsBound1(aViewNames.GetViewName()))
1244   {
1245     theDi << "Wrong view name\n";
1246     return 1;
1247   }
1248
1249   // Check if it is active already
1250   if (ViewerTest::CurrentView() == ViewerTest_myViews.Find1(aViewNames.GetViewName()))
1251   {
1252     theDi << theArgVec[0] << ": the view is active already\n";
1253     return 0;
1254   }
1255
1256   ActivateView (aViewNames.GetViewName());
1257   return 0;
1258 }
1259
1260 //==============================================================================
1261 //function : VViewList
1262 //purpose  : Print current list of views per viewer and graphic driver ID
1263 //           shared between viewers
1264 //==============================================================================
1265
1266 static int VViewList (Draw_Interpretor& theDi, Standard_Integer theArgsNb, const char** theArgVec)
1267 {
1268   if (theArgsNb > 2)
1269   {
1270     theDi << theArgVec[0] << ": Wrong number of command arguments\n"
1271           << "Usage: " << theArgVec[0] << " name";
1272     return 1;
1273   }
1274   if (ViewerTest_myContexts.Size() < 1)
1275     return 0;
1276
1277   Standard_Boolean isTreeView =
1278     (( theArgsNb==1 ) || ( strcasecmp( theArgVec[1], "long" ) != 0 ));
1279
1280   if (isTreeView)
1281     theDi << theArgVec[0] <<":\n";
1282
1283     for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
1284       aDriverIter(ViewerTest_myDrivers); aDriverIter.More(); aDriverIter.Next())
1285     {
1286       if (isTreeView)
1287         theDi << aDriverIter.Key1() << ":\n";
1288
1289       for (NCollection_DoubleMap <TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
1290         aContextIter(ViewerTest_myContexts); aContextIter.More(); aContextIter.Next())
1291       {
1292         if (aContextIter.Key1().Search(aDriverIter.Key1()) != -1)
1293         {
1294           if (isTreeView)
1295           {
1296             TCollection_AsciiString aContextName(aContextIter.Key1());
1297             theDi << " " << aContextName.Split(aDriverIter.Key1().Length() + 1) << ":\n";
1298           }
1299
1300           for (NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)>::Iterator
1301             aViewIter(ViewerTest_myViews); aViewIter.More(); aViewIter.Next())
1302           {
1303             if (aViewIter.Key1().Search(aContextIter.Key1()) != -1)
1304             {
1305               TCollection_AsciiString aViewName(aViewIter.Key1());
1306               if (isTreeView)
1307               {
1308                 if (aViewIter.Value() == ViewerTest::CurrentView())
1309                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "(*)\n";
1310                 else
1311                   theDi << "  " << aViewName.Split(aContextIter.Key1().Length() + 1) << "\n";
1312               }
1313               else
1314               {
1315                 theDi << aViewName << " ";
1316               }
1317             }
1318           }
1319         }
1320       }
1321     }
1322   return 0;
1323 }
1324
1325 //==============================================================================
1326 //function : VT_ProcessKeyPress
1327 //purpose  : Handle KeyPress event from a CString
1328 //==============================================================================
1329 void VT_ProcessKeyPress (const char* buf_ret)
1330 {
1331   //cout << "KeyPress" << endl;
1332   const Handle(V3d_View) aView = ViewerTest::CurrentView();
1333   // Letter in alphabetic order
1334
1335   if (!strcasecmp (buf_ret, "A"))
1336   {
1337     // AXO
1338     aView->SetProj(V3d_XposYnegZpos);
1339   }
1340   else if (!strcasecmp (buf_ret, "D"))
1341   {
1342     // Reset
1343     aView->Reset();
1344   }
1345   else if (!strcasecmp (buf_ret, "F"))
1346   {
1347     if (ViewerTest::GetAISContext()->NbSelected() > 0)
1348     {
1349       ViewerTest::GetAISContext()->FitSelected (aView);
1350     }
1351     else
1352     {
1353       // FitAll
1354       aView->FitAll();
1355     }
1356   }
1357   else if (!strcasecmp (buf_ret, "H"))
1358   {
1359     // HLR
1360     cout << "HLR" << endl;
1361     aView->SetComputedMode (!aView->ComputedMode());
1362     MyHLRIsOn = aView->ComputedMode();
1363   }
1364   else if (!strcasecmp (buf_ret, "P"))
1365   {
1366     // Type of HLR
1367     Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
1368     if (aContext->DefaultDrawer()->TypeOfHLR() == Prs3d_TOH_Algo)
1369       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_PolyAlgo);
1370     else
1371       aContext->DefaultDrawer()->SetTypeOfHLR(Prs3d_TOH_Algo);
1372     if (aContext->NbSelected()==0)
1373     {
1374       AIS_ListOfInteractive aListOfShapes;
1375       aContext->DisplayedObjects(aListOfShapes);
1376       for (AIS_ListIteratorOfListOfInteractive anIter(aListOfShapes);
1377         anIter.More(); anIter.Next())
1378       {
1379         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(anIter.Value());
1380         if (aShape.IsNull())
1381           continue;
1382         if (aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1383           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1384         else
1385           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1386         aContext->Redisplay (aShape, Standard_False);
1387       }
1388     }
1389     else
1390     {
1391       for (aContext->InitSelected();aContext->MoreSelected();aContext->NextSelected())
1392       {
1393         Handle(AIS_Shape) aShape = Handle(AIS_Shape)::DownCast(aContext->SelectedInteractive());
1394         if (aShape.IsNull())
1395           continue;
1396         if(aShape->TypeOfHLR() == Prs3d_TOH_PolyAlgo)
1397           aShape->SetTypeOfHLR (Prs3d_TOH_Algo);
1398         else
1399           aShape->SetTypeOfHLR (Prs3d_TOH_PolyAlgo);
1400         aContext->Redisplay (aShape, Standard_False);
1401       }
1402     }
1403
1404     aContext->UpdateCurrentViewer();
1405
1406   }
1407   else if (!strcasecmp (buf_ret, "S"))
1408   {
1409     std::cout << "setup Shaded display mode" << std::endl;
1410
1411     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1412     if(Ctx->NbSelected()==0)
1413       Ctx->SetDisplayMode(AIS_Shaded);
1414     else{
1415       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1416         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),1,Standard_False);
1417       Ctx->UpdateCurrentViewer();
1418     }
1419   }
1420   else if (!strcasecmp (buf_ret, "U"))
1421   {
1422     // Unset display mode
1423     std::cout << "reset display mode to defaults" << std::endl;
1424
1425     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1426     if(Ctx->NbSelected()==0)
1427       Ctx->SetDisplayMode(AIS_WireFrame);
1428     else{
1429       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1430         Ctx->UnsetDisplayMode(Ctx->SelectedInteractive(),Standard_False);
1431       Ctx->UpdateCurrentViewer();
1432     }
1433
1434   }
1435   else if (!strcasecmp (buf_ret, "T"))
1436   {
1437     // Top
1438     aView->SetProj(V3d_Zpos);
1439   }
1440   else if (!strcasecmp (buf_ret, "B"))
1441   {
1442     // Bottom
1443     aView->SetProj(V3d_Zneg);
1444   }
1445   else if (!strcasecmp (buf_ret, "L"))
1446   {
1447     // Left
1448     aView->SetProj(V3d_Xneg);
1449   }
1450   else if (!strcasecmp (buf_ret, "R"))
1451   {
1452     // Right
1453     aView->SetProj(V3d_Xpos);
1454   }
1455   else if (!strcasecmp (buf_ret, "W"))
1456   {
1457     std::cout << "setup WireFrame display mode" << std::endl;
1458     Handle(AIS_InteractiveContext) Ctx = ViewerTest::GetAISContext();
1459     if(Ctx->NbSelected()==0)
1460       Ctx->SetDisplayMode(AIS_WireFrame);
1461     else{
1462       for(Ctx->InitSelected();Ctx->MoreSelected();Ctx->NextSelected())
1463         Ctx->SetDisplayMode(Ctx->SelectedInteractive(),0,Standard_False);
1464       Ctx->UpdateCurrentViewer();
1465     }
1466   }
1467   else if (!strcasecmp (buf_ret, "Z"))
1468   {
1469     // ZCLIP
1470     if ( ZClipIsOn ) {
1471       cout << "ZClipping OFF" << endl;
1472       ZClipIsOn = 0;
1473
1474       aView->SetZClippingType(V3d_OFF);
1475       aView->Redraw();
1476     }
1477     else {
1478       cout << "ZClipping ON" << endl;
1479       ZClipIsOn = 1;
1480
1481       aView->SetZClippingType(V3d_FRONT);
1482       aView->Redraw();
1483     }
1484   }
1485   else if (!strcasecmp (buf_ret, ","))
1486   {
1487     ViewerTest::GetAISContext()->HilightNextDetected(ViewerTest::CurrentView());
1488   }
1489   else if (!strcasecmp (buf_ret, "."))
1490   {
1491     ViewerTest::GetAISContext()->HilightPreviousDetected(ViewerTest::CurrentView());
1492   }
1493   else if (!strcasecmp (buf_ret, "/"))
1494   {
1495     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1496     if (aCamera->IsStereo())
1497     {
1498       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() - 0.01);
1499       aView->Redraw();
1500     }
1501   }
1502   else if (!strcasecmp (buf_ret, "*"))
1503   {
1504     Handle(Graphic3d_Camera) aCamera = aView->Camera();
1505     if (aCamera->IsStereo())
1506     {
1507       aCamera->SetIOD (aCamera->GetIODType(), aCamera->IOD() + 0.01);
1508       aView->Redraw();
1509     }
1510   }
1511   else if (*buf_ret == THE_KEY_DELETE)
1512   {
1513     Handle(AIS_InteractiveContext) aCtx = ViewerTest::GetAISContext();
1514     if (!aCtx.IsNull()
1515      && aCtx->NbSelected() > 0)
1516     {
1517       Draw_Interprete ("verase");
1518     }
1519   }
1520   else
1521   {
1522     // Number
1523     Standard_Integer Num = Draw::Atoi(buf_ret);
1524     if(Num>=0 && Num<=7)
1525       ViewerTest::StandardModeActivation(Num);
1526   }
1527 }
1528
1529 //==============================================================================
1530 //function : VT_ProcessExpose
1531 //purpose  : Redraw the View on an Expose Event
1532 //==============================================================================
1533 void VT_ProcessExpose()
1534 {
1535   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1536   if (!aView3d.IsNull())
1537   {
1538     aView3d->Redraw();
1539   }
1540 }
1541
1542 //==============================================================================
1543 //function : VT_ProcessConfigure
1544 //purpose  : Resize the View on an Configure Event
1545 //==============================================================================
1546 void VT_ProcessConfigure()
1547 {
1548   Handle(V3d_View) aView3d = ViewerTest::CurrentView();
1549   if (aView3d.IsNull())
1550   {
1551     return;
1552   }
1553
1554   aView3d->MustBeResized();
1555   aView3d->Update();
1556   aView3d->Redraw();
1557 }
1558
1559 //==============================================================================
1560 //function : VT_ProcessButton1Press
1561 //purpose  : Picking
1562 //==============================================================================
1563 Standard_Boolean VT_ProcessButton1Press (Standard_Integer ,
1564                                          const char**     theArgVec,
1565                                          Standard_Boolean theToPick,
1566                                          Standard_Boolean theIsShift)
1567 {
1568   if (theToPick)
1569   {
1570     Standard_Real X, Y, Z;
1571     ViewerTest::CurrentView()->Convert (X_Motion, Y_Motion, X, Y, Z);
1572
1573     Draw::Set (theArgVec[1], X);
1574     Draw::Set (theArgVec[2], Y);
1575     Draw::Set (theArgVec[3], Z);
1576   }
1577
1578   if (theIsShift)
1579   {
1580     ViewerTest::CurrentEventManager()->ShiftSelect();
1581   }
1582   else
1583   {
1584     ViewerTest::CurrentEventManager()->Select();
1585   }
1586
1587   return Standard_False;
1588 }
1589
1590 //==============================================================================
1591 //function : VT_ProcessButton1Release
1592 //purpose  : End selecting
1593 //==============================================================================
1594 void VT_ProcessButton1Release (Standard_Boolean theIsShift)
1595 {
1596   if (IsDragged)
1597   {
1598     IsDragged = Standard_False;
1599     Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1600     if (theIsShift)
1601     {
1602       EM->ShiftSelect (X_ButtonPress, Y_ButtonPress,
1603                        X_Motion, Y_Motion);
1604     }
1605     else
1606     {
1607       EM->Select (X_ButtonPress, Y_ButtonPress,
1608                   X_Motion, Y_Motion);
1609     }
1610   }
1611 }
1612
1613 //==============================================================================
1614 //function : VT_ProcessButton3Press
1615 //purpose  : Start Rotation
1616 //==============================================================================
1617 void VT_ProcessButton3Press()
1618 {
1619   Start_Rot = 1;
1620   if (MyHLRIsOn)
1621   {
1622     ViewerTest::CurrentView()->SetComputedMode (Standard_False);
1623   }
1624   ViewerTest::CurrentView()->StartRotation( X_ButtonPress, Y_ButtonPress );
1625 }
1626
1627 //==============================================================================
1628 //function : VT_ProcessButton3Release
1629 //purpose  : End rotation
1630 //==============================================================================
1631 void VT_ProcessButton3Release()
1632 {
1633   if (Start_Rot)
1634   {
1635     Start_Rot = 0;
1636     if (MyHLRIsOn)
1637     {
1638       ViewerTest::CurrentView()->SetComputedMode (Standard_True);
1639     }
1640   }
1641 }
1642
1643 //==============================================================================
1644 //function : ProcessZClipMotion
1645 //purpose  : Zoom
1646 //==============================================================================
1647
1648 void ProcessZClipMotion()
1649 {
1650   Handle(V3d_View)  a3DView = ViewerTest::CurrentView();
1651   if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
1652
1653     //Quantity_Length VDX, VDY;
1654     //a3DView->Size(VDX,VDY);
1655     //Standard_Real VDZ = a3DView->ZSize();
1656     //printf("View size (%lf,%lf,%lf)\n", VDX, VDY, VDZ);
1657
1658     Quantity_Length aDx = a3DView->Convert(X_Motion - X_ButtonPress);
1659
1660     // Front = Depth + width/2.
1661     Standard_Real aDepth = 0.5;
1662     Standard_Real aWidth = 0.1;
1663     a3DView->ZClipping(aDepth,aWidth);
1664
1665     aDepth += aDx;
1666
1667     //printf("dx %lf Depth %lf Width %lf\n", dx, D, W);
1668
1669     a3DView->SetZClippingDepth(aDepth);
1670
1671     a3DView->Redraw();
1672
1673     X_ButtonPress = X_Motion;
1674     Y_ButtonPress = Y_Motion;
1675   }
1676 }
1677
1678 //==============================================================================
1679 //function : ProcessControlButton1Motion
1680 //purpose  : Zoom
1681 //==============================================================================
1682
1683 #if defined(_WIN32) || ! defined(__APPLE__) || defined(MACOSX_USE_GLX)
1684 static void ProcessControlButton1Motion()
1685 {
1686   ViewerTest::CurrentView()->Zoom( X_ButtonPress, Y_ButtonPress, X_Motion, Y_Motion);
1687
1688   X_ButtonPress = X_Motion;
1689   Y_ButtonPress = Y_Motion;
1690 }
1691 #endif
1692
1693 //==============================================================================
1694 //function : VT_ProcessControlButton2Motion
1695 //purpose  : Panning
1696 //==============================================================================
1697 void VT_ProcessControlButton2Motion()
1698 {
1699   Standard_Integer aDx = X_Motion - X_ButtonPress;
1700   Standard_Integer aDy = Y_Motion - Y_ButtonPress;
1701
1702   aDy = -aDy; // Xwindow Y axis is from top to Bottom
1703
1704   ViewerTest::CurrentView()->Pan (aDx, aDy);
1705
1706   X_ButtonPress = X_Motion;
1707   Y_ButtonPress = Y_Motion;
1708 }
1709
1710 //==============================================================================
1711 //function : VT_ProcessControlButton3Motion
1712 //purpose  : Rotation
1713 //==============================================================================
1714 void VT_ProcessControlButton3Motion()
1715 {
1716   if (Start_Rot)
1717   {
1718     ViewerTest::CurrentView()->Rotation (X_Motion, Y_Motion);
1719   }
1720 }
1721
1722 //==============================================================================
1723 //function : VT_ProcessMotion
1724 //purpose  :
1725 //==============================================================================
1726 void VT_ProcessMotion()
1727 {
1728   //pre-hilights detected objects at mouse position
1729
1730   Handle(ViewerTest_EventManager) EM = ViewerTest::CurrentEventManager();
1731   EM->MoveTo(X_Motion, Y_Motion);
1732 }
1733
1734
1735 void ViewerTest::GetMousePosition(Standard_Integer& Xpix,Standard_Integer& Ypix)
1736 {
1737   Xpix = X_Motion;Ypix=Y_Motion;
1738 }
1739
1740 //==============================================================================
1741 //function : ViewProject: implements VAxo, VTop, VLeft, ...
1742 //purpose  : Switches to an axonometric, top, left and other views
1743 //==============================================================================
1744
1745 static int ViewProject(Draw_Interpretor& di, const V3d_TypeOfOrientation ori)
1746 {
1747   if ( ViewerTest::CurrentView().IsNull() )
1748   {
1749     di<<"Call vinit before this command, please\n";
1750     return 1;
1751   }
1752
1753   ViewerTest::CurrentView()->SetProj(ori);
1754   return 0;
1755 }
1756
1757 //==============================================================================
1758 //function : VAxo
1759 //purpose  : Switch to an Axonometric view
1760 //Draw arg : No args
1761 //==============================================================================
1762
1763 static int VAxo(Draw_Interpretor& di, Standard_Integer , const char** )
1764 {
1765   return ViewProject(di, V3d_XposYnegZpos);
1766 }
1767
1768 //==============================================================================
1769 //function : VTop
1770 //purpose  : Switch to a Top View
1771 //Draw arg : No args
1772 //==============================================================================
1773
1774 static int VTop(Draw_Interpretor& di, Standard_Integer , const char** )
1775 {
1776   return ViewProject(di, V3d_Zpos);
1777 }
1778
1779 //==============================================================================
1780 //function : VBottom
1781 //purpose  : Switch to a Bottom View
1782 //Draw arg : No args
1783 //==============================================================================
1784
1785 static int VBottom(Draw_Interpretor& di, Standard_Integer , const char** )
1786 {
1787   return ViewProject(di, V3d_Zneg);
1788 }
1789
1790 //==============================================================================
1791 //function : VLeft
1792 //purpose  : Switch to a Left View
1793 //Draw arg : No args
1794 //==============================================================================
1795
1796 static int VLeft(Draw_Interpretor& di, Standard_Integer , const char** )
1797 {
1798   return ViewProject(di, V3d_Xneg);
1799 }
1800
1801 //==============================================================================
1802 //function : VRight
1803 //purpose  : Switch to a Right View
1804 //Draw arg : No args
1805 //==============================================================================
1806
1807 static int VRight(Draw_Interpretor& di, Standard_Integer , const char** )
1808 {
1809   return ViewProject(di, V3d_Xpos);
1810 }
1811
1812 //==============================================================================
1813 //function : VFront
1814 //purpose  : Switch to a Front View
1815 //Draw arg : No args
1816 //==============================================================================
1817
1818 static int VFront(Draw_Interpretor& di, Standard_Integer , const char** )
1819 {
1820   return ViewProject(di, V3d_Yneg);
1821 }
1822
1823 //==============================================================================
1824 //function : VBack
1825 //purpose  : Switch to a Back View
1826 //Draw arg : No args
1827 //==============================================================================
1828
1829 static int VBack(Draw_Interpretor& di, Standard_Integer , const char** )
1830 {
1831   return ViewProject(di, V3d_Ypos);
1832 }
1833
1834 //==============================================================================
1835 //function : VHelp
1836 //purpose  : Dsiplay help on viewer Keyboead and mouse commands
1837 //Draw arg : No args
1838 //==============================================================================
1839
1840 static int VHelp(Draw_Interpretor& di, Standard_Integer , const char** )
1841 {
1842
1843   di << "Q : Quit the application\n";
1844
1845   di << "=========================\n";
1846   di << "F : FitAll\n";
1847   di << "T : TopView\n";
1848   di << "B : BottomView\n";
1849   di << "R : RightView\n";
1850   di << "L : LeftView\n";
1851   di << "A : AxonometricView\n";
1852   di << "D : ResetView\n";
1853
1854   di << "=========================\n";
1855   di << "S : Shading\n";
1856   di << "W : Wireframe\n";
1857   di << "H : HidelLineRemoval\n";
1858   di << "U : Unset display mode\n";
1859   di << "Delete : Remove selection from viewer\n";
1860
1861   di << "=========================\n";
1862   di << "Selection mode \n";
1863   di << "0 : Shape\n";
1864   di << "1 : Vertex\n";
1865   di << "2 : Edge\n";
1866   di << "3 : Wire\n";
1867   di << "4 : Face\n";
1868   di << "5 : Shell\n";
1869   di << "6 : Solid\n";
1870   di << "7 : Compound\n";
1871
1872   di << "=========================\n";
1873   di << "Z : Switch Z clipping On/Off\n";
1874   di << ", : Hilight next detected\n";
1875   di << ". : Hilight previous detected\n";
1876
1877   return 0;
1878 }
1879
1880 #ifdef _WIN32
1881
1882 static Standard_Boolean Ppick = 0;
1883 static Standard_Integer Pargc = 0;
1884 static const char**           Pargv = NULL;
1885
1886
1887 static LRESULT WINAPI AdvViewerWindowProc( HWND hwnd,
1888                                           UINT Msg,
1889                                           WPARAM wParam,
1890                                           LPARAM lParam )
1891 {
1892   if (!ViewerTest_myViews.IsEmpty()) {
1893
1894     WPARAM fwKeys = wParam;
1895
1896     switch( Msg ) {
1897     case WM_CLOSE:
1898        {
1899          // Delete view from map of views
1900          ViewerTest::RemoveView(FindViewIdByWindowHandle(hwnd));
1901          return 0;
1902        }
1903        break;
1904     case WM_ACTIVATE:
1905       if(LOWORD(wParam) == WA_CLICKACTIVE || LOWORD(wParam) == WA_ACTIVE
1906         || ViewerTest::CurrentView().IsNull())
1907       {
1908         // Activate inactive window
1909         if(GetWindowHandle(VT_GetWindow()) != hwnd)
1910         {
1911           ActivateView (FindViewIdByWindowHandle(hwnd));
1912         }
1913       }
1914       break;
1915     case WM_LBUTTONUP:
1916       if (!DragFirst)
1917       {
1918         if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1919         {
1920           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1921           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1922         }
1923
1924         VT_ProcessButton1Release (fwKeys & MK_SHIFT);
1925       }
1926       IsDragged = Standard_False;
1927       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1928
1929     case WM_LBUTTONDOWN:
1930       if( fwKeys == MK_LBUTTON || fwKeys == ( MK_LBUTTON | MK_SHIFT ) )
1931       {
1932         IsDragged = Standard_True;
1933         DragFirst = Standard_True;
1934         X_ButtonPress = LOWORD(lParam);
1935         Y_ButtonPress = HIWORD(lParam);
1936       }
1937       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1938
1939       break;
1940
1941     case WM_MOUSEMOVE:
1942       if (IsDragged)
1943       {
1944         bool toRedraw = false;
1945         if (!DragFirst && ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
1946         {
1947           ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
1948           toRedraw = true;
1949         }
1950
1951         DragFirst = Standard_False;
1952         X_Motion = LOWORD (lParam);
1953         Y_Motion = HIWORD (lParam);
1954
1955         RECT aRect;
1956         if (GetClientRect (hwnd, &aRect))
1957         {
1958           int aHeight = aRect.bottom - aRect.top;
1959           GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
1960           ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
1961           toRedraw = true;
1962         }
1963         if (toRedraw)
1964         {
1965           ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
1966         }
1967       }
1968       else
1969         return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1970       break;
1971
1972     default:
1973       return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1974     }
1975     return 0;
1976   }
1977   return ViewerWindowProc( hwnd, Msg, wParam, lParam );
1978 }
1979
1980
1981 static LRESULT WINAPI ViewerWindowProc( HWND hwnd,
1982                                        UINT Msg,
1983                                        WPARAM wParam,
1984                                        LPARAM lParam )
1985 {
1986   static int Up = 1;
1987   const Handle(V3d_View)& aView = ViewerTest::CurrentView();
1988   if (aView.IsNull())
1989   {
1990     return DefWindowProc( hwnd, Msg, wParam, lParam );
1991   }
1992
1993     PAINTSTRUCT    ps;
1994
1995     switch( Msg ) {
1996     case WM_PAINT:
1997       BeginPaint(hwnd, &ps);
1998       EndPaint(hwnd, &ps);
1999       VT_ProcessExpose();
2000       break;
2001
2002     case WM_SIZE:
2003       VT_ProcessConfigure();
2004       break;
2005     case WM_MOVE:
2006     case WM_MOVING:
2007     case WM_SIZING:
2008       switch (aView->RenderingParams().StereoMode)
2009       {
2010         case Graphic3d_StereoMode_RowInterlaced:
2011         case Graphic3d_StereoMode_ColumnInterlaced:
2012         case Graphic3d_StereoMode_ChessBoard:
2013           VT_ProcessConfigure(); // track window moves to reverse stereo pair
2014           break;
2015         default:
2016           break;
2017       }
2018       break;
2019
2020     case WM_KEYDOWN:
2021       if ((wParam != VK_SHIFT) && (wParam != VK_CONTROL))
2022       {
2023         char c[2];
2024         c[0] = (char) wParam;
2025         c[1] = '\0';
2026         if (wParam == VK_DELETE)
2027         {
2028           c[0] = THE_KEY_DELETE;
2029         }
2030         // comma
2031         else if (wParam == VK_OEM_COMMA)
2032         {
2033           c[0] = ',';
2034         }
2035         // dot
2036         else if (wParam == VK_OEM_PERIOD)
2037         {
2038           c[0] = '.';
2039         }
2040         else if (wParam == VK_DIVIDE)
2041         {
2042           c[0] = '/';
2043         }
2044         // dot
2045         else if (wParam == VK_MULTIPLY)
2046         {
2047           c[0] = '*';
2048         }
2049         VT_ProcessKeyPress (c);
2050       }
2051       break;
2052
2053     case WM_LBUTTONUP:
2054     case WM_MBUTTONUP:
2055     case WM_RBUTTONUP:
2056       Up = 1;
2057       VT_ProcessButton3Release();
2058       break;
2059
2060     case WM_LBUTTONDOWN:
2061     case WM_MBUTTONDOWN:
2062     case WM_RBUTTONDOWN:
2063       {
2064         WPARAM fwKeys = wParam;
2065
2066         Up = 0;
2067
2068         X_ButtonPress = LOWORD(lParam);
2069         Y_ButtonPress = HIWORD(lParam);
2070
2071         if (Msg == WM_LBUTTONDOWN)
2072         {
2073           if (fwKeys & MK_CONTROL)
2074           {
2075             Ppick = VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT));
2076           }
2077           else
2078           {
2079             VT_ProcessButton1Press (Pargc, Pargv, Ppick, (fwKeys & MK_SHIFT));
2080           }
2081         }
2082         else if (Msg == WM_RBUTTONDOWN)
2083         {
2084           // Start rotation
2085           VT_ProcessButton3Press();
2086         }
2087       }
2088       break;
2089
2090     case WM_MOUSEWHEEL:
2091     {
2092       int aDelta = GET_WHEEL_DELTA_WPARAM (wParam);
2093       if (wParam & MK_CONTROL)
2094       {
2095         if (aView->Camera()->IsStereo())
2096         {
2097           Standard_Real aFocus = aView->Camera()->ZFocus() + (aDelta > 0 ? 0.05 : -0.05);
2098           if (aFocus > 0.2
2099            && aFocus < 2.0)
2100           {
2101             aView->Camera()->SetZFocus (aView->Camera()->ZFocusType(), aFocus);
2102             aView->Redraw();
2103           }
2104         }
2105       }
2106       else
2107       {
2108         aView->Zoom (0, 0, aDelta / 40, aDelta / 40);
2109       }
2110       break;
2111     }
2112
2113     case WM_MOUSEMOVE:
2114       {
2115         //cout << "\t WM_MOUSEMOVE" << endl;
2116         WPARAM fwKeys = wParam;
2117         X_Motion = LOWORD(lParam);
2118         Y_Motion = HIWORD(lParam);
2119
2120         if ( Up &&
2121           fwKeys & ( MK_LBUTTON|MK_MBUTTON|MK_RBUTTON ) ) {
2122             Up = 0;
2123             X_ButtonPress = LOWORD(lParam);
2124             Y_ButtonPress = HIWORD(lParam);
2125
2126             if ( fwKeys & MK_RBUTTON ) {
2127               // Start rotation
2128               VT_ProcessButton3Press();
2129             }
2130           }
2131
2132           if ( fwKeys & MK_CONTROL ) {
2133             if ( fwKeys & MK_LBUTTON ) {
2134               ProcessControlButton1Motion();
2135             }
2136             else if ( fwKeys & MK_MBUTTON ||
2137               ((fwKeys&MK_LBUTTON) &&
2138               (fwKeys&MK_RBUTTON) ) ){
2139                 VT_ProcessControlButton2Motion();
2140               }
2141             else if ( fwKeys & MK_RBUTTON ) {
2142               VT_ProcessControlButton3Motion();
2143             }
2144           }
2145 #ifdef BUG
2146           else if ( fwKeys & MK_SHIFT ) {
2147             if ( fwKeys & MK_MBUTTON ||
2148               ((fwKeys&MK_LBUTTON) &&
2149               (fwKeys&MK_RBUTTON) ) ) {
2150                 cout << "ProcessZClipMotion()" << endl;
2151                 ProcessZClipMotion();
2152               }
2153           }
2154 #endif
2155           else if (GetWindowHandle (VT_GetWindow()) == hwnd)
2156           {
2157             if ((fwKeys & MK_MBUTTON
2158             || ((fwKeys & MK_LBUTTON) && (fwKeys & MK_RBUTTON))))
2159             {
2160               ProcessZClipMotion();
2161             }
2162             else
2163             {
2164               VT_ProcessMotion();
2165             }
2166           }
2167       }
2168       break;
2169
2170     default:
2171       return( DefWindowProc( hwnd, Msg, wParam, lParam ));
2172     }
2173     return 0L;
2174 }
2175
2176
2177
2178
2179 //==============================================================================
2180 //function : ViewerMainLoop
2181 //purpose  : Get a Event on the view and dispatch it
2182 //==============================================================================
2183
2184
2185 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2186 {
2187   Ppick = (argc > 0)? 1 : 0;
2188   Pargc = argc;
2189   Pargv = argv;
2190
2191   if ( Ppick ) {
2192     MSG msg;
2193     msg.wParam = 1;
2194
2195     cout << "Start picking" << endl;
2196
2197     while ( Ppick == 1 ) {
2198       // Wait for a VT_ProcessButton1Press() to toggle pick to 1 or 0
2199       if (GetMessage(&msg, NULL, 0, 0) ) {
2200         TranslateMessage(&msg);
2201         DispatchMessage(&msg);
2202       }
2203     }
2204
2205     cout << "Picking done" << endl;
2206   }
2207
2208   return Ppick;
2209 }
2210
2211 #elif !defined(__APPLE__) || defined(MACOSX_USE_GLX)
2212
2213 int min( int a, int b )
2214 {
2215   if( a<b )
2216     return a;
2217   else
2218     return b;
2219 }
2220
2221 int max( int a, int b )
2222 {
2223   if( a>b )
2224     return a;
2225   else
2226     return b;
2227 }
2228
2229 int ViewerMainLoop(Standard_Integer argc, const char** argv)
2230
2231 {
2232   static XEvent aReport;
2233   Standard_Boolean pick = argc > 0;
2234   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2235   XNextEvent (aDisplay, &aReport);
2236
2237   // Handle event for the chosen display connection
2238   switch (aReport.type) {
2239       case ClientMessage:
2240         {
2241           if((Atom)aReport.xclient.data.l[0] == GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW))
2242           {
2243             // Close the window
2244             ViewerTest::RemoveView(FindViewIdByWindowHandle (aReport.xclient.window));
2245           }
2246         }
2247         return 0;
2248      case FocusIn:
2249       {
2250          // Activate inactive view
2251          Window aWindow = GetWindowHandle(VT_GetWindow());
2252          if(aWindow != aReport.xfocus.window)
2253          {
2254            ActivateView (FindViewIdByWindowHandle (aReport.xfocus.window));
2255          }
2256       }
2257       break;
2258       case Expose:
2259         {
2260           VT_ProcessExpose();
2261         }
2262         break;
2263       case ConfigureNotify:
2264         {
2265           VT_ProcessConfigure();
2266         }
2267         break;
2268       case KeyPress:
2269         {
2270
2271           KeySym ks_ret ;
2272           char buf_ret[11] ;
2273           int ret_len ;
2274           XComposeStatus status_in_out;
2275
2276           ret_len = XLookupString( ( XKeyEvent *)&aReport ,
2277             (char *) buf_ret , 10 ,
2278             &ks_ret , &status_in_out ) ;
2279
2280
2281           buf_ret[ret_len] = '\0' ;
2282
2283           if (ret_len)
2284           {
2285             VT_ProcessKeyPress (buf_ret);
2286           }
2287         }
2288         break;
2289       case ButtonPress:
2290         {
2291           X_ButtonPress = aReport.xbutton.x;
2292           Y_ButtonPress = aReport.xbutton.y;
2293
2294           if (aReport.xbutton.button == Button1)
2295           {
2296             if (aReport.xbutton.state & ControlMask)
2297             {
2298               pick = VT_ProcessButton1Press (argc, argv, pick, (aReport.xbutton.state & ShiftMask));
2299             }
2300             else
2301             {
2302               IsDragged = Standard_True;
2303               DragFirst = Standard_True;
2304             }
2305           }
2306           else if (aReport.xbutton.button == Button3)
2307           {
2308             // Start rotation
2309             VT_ProcessButton3Press();
2310           }
2311         }
2312         break;
2313       case ButtonRelease:
2314         {
2315           if( IsDragged )
2316           {
2317             if( !DragFirst )
2318             {
2319               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2320               {
2321                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2322                 ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2323               }
2324             }
2325
2326             Handle( AIS_InteractiveContext ) aContext = ViewerTest::GetAISContext();
2327             if( aContext.IsNull() )
2328             {
2329               cout << "The context is null. Please use vinit before createmesh" << endl;
2330               return 0;
2331             }
2332
2333             Standard_Boolean ShiftPressed = ( aReport.xbutton.state & ShiftMask );
2334             if( aReport.xbutton.button==1 )
2335               if( DragFirst )
2336                 if( ShiftPressed )
2337                 {
2338                   aContext->ShiftSelect();
2339                 }
2340                 else
2341                 {
2342                   aContext->Select();
2343                 }
2344               else
2345                 if( ShiftPressed )
2346                 {
2347                   aContext->ShiftSelect( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2348                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2349                     ViewerTest::CurrentView());
2350                 }
2351                 else
2352                 {
2353                   aContext->Select( min( X_ButtonPress, X_Motion ), min( Y_ButtonPress, Y_Motion ),
2354                     max( X_ButtonPress, X_Motion ), max( Y_ButtonPress, Y_Motion ),
2355                     ViewerTest::CurrentView() );
2356                 }
2357             else
2358               VT_ProcessButton3Release();
2359
2360             IsDragged = Standard_False;
2361           }
2362           else
2363             VT_ProcessButton3Release();
2364         }
2365         break;
2366       case MotionNotify:
2367         {
2368           if (GetWindowHandle (VT_GetWindow()) != aReport.xmotion.window)
2369           {
2370             break;
2371           }
2372           if( IsDragged )
2373           {
2374             if( !DragFirst )
2375             {
2376               if (ViewerTest::GetAISContext()->IsDisplayed (GetRubberBand()))
2377               {
2378                 ViewerTest::GetAISContext()->Remove (GetRubberBand(), Standard_False);
2379               }
2380             }
2381
2382             X_Motion = aReport.xmotion.x;
2383             Y_Motion = aReport.xmotion.y;
2384             DragFirst = Standard_False;
2385
2386             Window aWindow = GetWindowHandle(VT_GetWindow());
2387             Window aRoot;
2388             int anX, anY;
2389             unsigned int aWidth, aHeight, aBorderWidth, aDepth;
2390             XGetGeometry (aDisplay, aWindow, &aRoot, &anX, &anY, &aWidth, &aHeight, &aBorderWidth, &aDepth);
2391             GetRubberBand()->SetRectangle (X_ButtonPress, aHeight - Y_ButtonPress, X_Motion, aHeight - Y_Motion);
2392             ViewerTest::GetAISContext()->Display (GetRubberBand(), 0, -1, Standard_False, Standard_True, AIS_DS_Displayed);
2393             ViewerTest::GetAISContext()->CurrentViewer()->RedrawImmediate();
2394           }
2395           else
2396           {
2397             X_Motion = aReport.xmotion.x;
2398             Y_Motion = aReport.xmotion.y;
2399
2400             // remove all the ButtonMotionMaskr
2401             while( XCheckMaskEvent( aDisplay, ButtonMotionMask, &aReport) ) ;
2402
2403             if ( ZClipIsOn && aReport.xmotion.state & ShiftMask ) {
2404               if ( Abs(X_Motion - X_ButtonPress) > 2 ) {
2405
2406                 Quantity_Length VDX, VDY;
2407
2408                 ViewerTest::CurrentView()->Size(VDX,VDY);
2409                 Standard_Real VDZ =0 ;
2410                 VDZ = ViewerTest::CurrentView()->ZSize();
2411
2412                 printf("%f,%f,%f\n", VDX, VDY, VDZ);
2413
2414                 Quantity_Length dx = 0 ;
2415                 dx = ViewerTest::CurrentView()->Convert(X_Motion - X_ButtonPress);
2416
2417                 cout << dx << endl;
2418
2419                 dx = dx / VDX * VDZ;
2420
2421                 cout << dx << endl;
2422
2423                 ViewerTest::CurrentView()->Redraw();
2424               }
2425             }
2426
2427             if ( aReport.xmotion.state & ControlMask ) {
2428               if ( aReport.xmotion.state & Button1Mask ) {
2429                 ProcessControlButton1Motion();
2430               }
2431               else if ( aReport.xmotion.state & Button2Mask ) {
2432                 VT_ProcessControlButton2Motion();
2433               }
2434               else if ( aReport.xmotion.state & Button3Mask ) {
2435                 VT_ProcessControlButton3Motion();
2436               }
2437             }
2438             else
2439             {
2440               VT_ProcessMotion();
2441             }
2442           }
2443         }
2444         break;
2445 }
2446 return pick;
2447 }
2448
2449 //==============================================================================
2450 //function : VProcessEvents
2451 //purpose  : call by Tk_CreateFileHandler() to be able to manage the
2452 //       event in the Viewer window
2453 //==============================================================================
2454
2455 static void VProcessEvents(ClientData,int)
2456 {
2457   NCollection_Vector<int> anEventNumbers;
2458   // Get number of messages from every display
2459   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2460        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next())
2461   {
2462     anEventNumbers.Append(XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()));
2463   }
2464     // Handle events for every display
2465   int anEventIter = 0;
2466   for (NCollection_DoubleMap <TCollection_AsciiString, Handle(Graphic3d_GraphicDriver)>::Iterator
2467        anIter (ViewerTest_myDrivers); anIter.More(); anIter.Next(), anEventIter++)
2468   {
2469     for (int i = 0; i < anEventNumbers.Value(anEventIter) &&
2470          XPending (anIter.Key2()->GetDisplayConnection()->GetDisplay()) > 0; ++i)
2471     {
2472       SetDisplayConnection (anIter.Key2()->GetDisplayConnection());
2473       int anEventResult = ViewerMainLoop( 0, NULL);
2474       // If window is closed or context was not found finish current event processing loop
2475       if (!anEventResult)
2476         return;
2477     }
2478   }
2479
2480   SetDisplayConnection (ViewerTest::GetAISContext()->CurrentViewer()->Driver()->GetDisplayConnection());
2481
2482 }
2483 #endif
2484
2485 //==============================================================================
2486 //function : OSWindowSetup
2487 //purpose  : Setup for the X11 window to be able to cath the event
2488 //==============================================================================
2489
2490
2491 static void OSWindowSetup()
2492 {
2493 #if !defined(_WIN32) && !defined(__WIN32__) && (!defined(__APPLE__) || defined(MACOSX_USE_GLX))
2494   // X11
2495
2496   Window  window   = VT_GetWindow()->XWindow();
2497   SetDisplayConnection (ViewerTest::CurrentView()->Viewer()->Driver()->GetDisplayConnection());
2498   Display *aDisplay = GetDisplayConnection()->GetDisplay();
2499   XSynchronize(aDisplay, 1);
2500
2501   // X11 : For keyboard on SUN
2502   XWMHints wmhints;
2503   wmhints.flags = InputHint;
2504   wmhints.input = 1;
2505
2506   XSetWMHints( aDisplay, window, &wmhints);
2507
2508   XSelectInput( aDisplay, window,  ExposureMask | KeyPressMask |
2509     ButtonPressMask | ButtonReleaseMask |
2510     StructureNotifyMask |
2511     PointerMotionMask |
2512     Button1MotionMask | Button2MotionMask |
2513     Button3MotionMask | FocusChangeMask
2514     );
2515   Atom aDeleteWindowAtom = GetDisplayConnection()->GetAtom(Aspect_XA_DELETE_WINDOW);
2516   XSetWMProtocols(aDisplay, window, &aDeleteWindowAtom, 1);
2517
2518   XSynchronize(aDisplay, 0);
2519
2520 #else
2521   // _WIN32
2522 #endif
2523
2524 }
2525
2526 //==============================================================================
2527 //function : VFit
2528
2529 //purpose  : Fitall, no DRAW arguments
2530 //Draw arg : No args
2531 //==============================================================================
2532
2533 static int VFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgc, const char** theArgv)
2534 {
2535   if (theArgc > 2)
2536   {
2537     std::cout << "Wrong number of arguments! Use: vfit [-selected]" << std::endl;
2538   }
2539
2540   const Handle(V3d_View) aView = ViewerTest::CurrentView();
2541
2542   if (theArgc == 2)
2543   {
2544     TCollection_AsciiString anArg (theArgv[1]);
2545     anArg.LowerCase();
2546     if (anArg == "-selected")
2547     {
2548       ViewerTest::GetAISContext()->FitSelected (aView);
2549       return 0;
2550     }
2551   }
2552   if (aView.IsNull() == Standard_False) {
2553
2554     aView->FitAll();
2555   }
2556   return 0;
2557 }
2558
2559 //=======================================================================
2560 //function : VFitArea
2561 //purpose  : Fit view to show area located between two points
2562 //         : given in world 2D or 3D coordinates.
2563 //=======================================================================
2564 static int VFitArea (Draw_Interpretor& theDI, Standard_Integer  theArgNb, const char** theArgVec)
2565 {
2566   Handle(V3d_View) aView = ViewerTest::CurrentView();
2567   if (aView.IsNull())
2568   {
2569     std::cerr << theArgVec[0] << "Error: No active view.\n";
2570     return 1;
2571   }
2572
2573   // Parse arguments.
2574   gp_Pnt aWorldPnt1 (0.0, 0.0, 0.0);
2575   gp_Pnt aWorldPnt2 (0.0, 0.0, 0.0);
2576
2577   if (theArgNb == 5)
2578   {
2579     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2580     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2581     aWorldPnt2.SetX (Draw::Atof (theArgVec[3]));
2582     aWorldPnt2.SetY (Draw::Atof (theArgVec[4]));
2583   }
2584   else if (theArgNb == 7)
2585   {
2586     aWorldPnt1.SetX (Draw::Atof (theArgVec[1]));
2587     aWorldPnt1.SetY (Draw::Atof (theArgVec[2]));
2588     aWorldPnt1.SetZ (Draw::Atof (theArgVec[3]));
2589     aWorldPnt2.SetX (Draw::Atof (theArgVec[4]));
2590     aWorldPnt2.SetY (Draw::Atof (theArgVec[5]));
2591     aWorldPnt2.SetZ (Draw::Atof (theArgVec[6]));
2592   }
2593   else
2594   {
2595     std::cerr << theArgVec[0] << "Error: Invalid number of arguments.\n";
2596     theDI.PrintHelp(theArgVec[0]);
2597     return 1;
2598   }
2599
2600   // Convert model coordinates to view space
2601   Handle(Graphic3d_Camera) aCamera = aView->Camera();
2602   gp_Pnt aViewPnt1 = aCamera->ConvertWorld2View (aWorldPnt1);
2603   gp_Pnt aViewPnt2 = aCamera->ConvertWorld2View (aWorldPnt2);
2604
2605   // Determine fit area
2606   gp_Pnt2d aMinCorner (Min (aViewPnt1.X(), aViewPnt2.X()), Min (aViewPnt1.Y(), aViewPnt2.Y()));
2607   gp_Pnt2d aMaxCorner (Max (aViewPnt1.X(), aViewPnt2.X()), Max (aViewPnt1.Y(), aViewPnt2.Y()));
2608
2609   Standard_Real aDiagonal = aMinCorner.Distance (aMaxCorner);
2610
2611   if (aDiagonal < Precision::Confusion())
2612   {
2613     std::cerr << theArgVec[0] << "Error: view area is too small.\n";
2614     return 1;
2615   }
2616
2617   aView->FitAll (aMinCorner.X(), aMinCorner.Y(), aMaxCorner.X(), aMaxCorner.Y());
2618   return 0;
2619 }
2620
2621 //==============================================================================
2622 //function : VZFit
2623 //purpose  : ZFitall, no DRAW arguments
2624 //Draw arg : No args
2625 //==============================================================================
2626 static int VZFit (Draw_Interpretor& /*theDi*/, Standard_Integer theArgsNb, const char** theArgVec)
2627 {
2628   const Handle(V3d_View)& aCurrentView = ViewerTest::CurrentView();
2629
2630   if (aCurrentView.IsNull())
2631   {
2632     std::cout << theArgVec[0] << ": Call vinit before this command, please.\n";
2633     return 1;
2634   }
2635
2636   if (theArgsNb == 1)
2637   {
2638     aCurrentView->ZFitAll();
2639     aCurrentView->Redraw();
2640     return 0;
2641   }
2642
2643   Standard_Real aScale = 1.0;
2644
2645   if (theArgsNb >= 2)
2646   {
2647     aScale = Draw::Atoi (theArgVec[1]);
2648   }
2649
2650   aCurrentView->ZFitAll (aScale);
2651   aCurrentView->Redraw();
2652
2653   return 0;
2654 }
2655
2656 //==============================================================================
2657 //function : VRepaint
2658 //purpose  :
2659 //==============================================================================
2660 static int VRepaint (Draw_Interpretor& , Standard_Integer , const char** )
2661 {
2662   Handle(V3d_View) V = ViewerTest::CurrentView();
2663   if ( !V.IsNull() ) V->Redraw(); return 0;
2664 }
2665
2666 //==============================================================================
2667 //function : VClear
2668 //purpose  : Remove all the object from the viewer
2669 //Draw arg : No args
2670 //==============================================================================
2671
2672 static int VClear(Draw_Interpretor& , Standard_Integer , const char** )
2673 {
2674   Handle(V3d_View) V = ViewerTest::CurrentView();
2675   if(!V.IsNull())
2676     ViewerTest::Clear();
2677   return 0;
2678 }
2679
2680 //==============================================================================
2681 //function : VPick
2682 //purpose  :
2683 //==============================================================================
2684
2685 static int VPick(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2686 { if (ViewerTest::CurrentView().IsNull() ) return 1;
2687
2688 if ( argc < 4 ) {
2689   di << argv[0] << "Invalid number of arguments\n";
2690   return 1;
2691 }
2692
2693 while (ViewerMainLoop( argc, argv)) {
2694 }
2695
2696 return 0;
2697 }
2698
2699 //==============================================================================
2700 //function : VSetBg
2701 //purpose  : Load image as background
2702 //==============================================================================
2703
2704 static int VSetBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2705 {
2706   if (argc < 2 || argc > 3)
2707   {
2708     di << "Usage : " << argv[0] << " imagefile [filltype] : Load image as background\n";
2709     di << "filltype can be one of CENTERED, TILED, STRETCH, NONE\n";
2710     return 1;
2711   }
2712
2713   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2714   if(AISContext.IsNull())
2715   {
2716     di << "use 'vinit' command before " << argv[0] << "\n";
2717     return 1;
2718   }
2719
2720   Aspect_FillMethod aFillType = Aspect_FM_CENTERED;
2721   if (argc == 3)
2722   {
2723     const char* szType = argv[2];
2724     if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2725     else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2726     else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2727     else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2728     else
2729     {
2730       di << "Wrong fill type : " << szType << "\n";
2731       di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2732       return 1;
2733     }
2734   }
2735
2736   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2737   V3dView->SetBackgroundImage(argv[1], aFillType, Standard_True);
2738
2739   return 0;
2740 }
2741
2742 //==============================================================================
2743 //function : VSetBgMode
2744 //purpose  : Change background image fill type
2745 //==============================================================================
2746
2747 static int VSetBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2748 {
2749   if (argc != 2)
2750   {
2751     di << "Usage : " << argv[0] << " filltype : Change background image mode\n";
2752     di << "filltype must be one of CENTERED, TILED, STRETCH, NONE\n";
2753     return 1;
2754   }
2755
2756   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2757   if(AISContext.IsNull())
2758   {
2759     di << "use 'vinit' command before " << argv[0] << "\n";
2760     return 1;
2761   }
2762   Aspect_FillMethod aFillType = Aspect_FM_NONE;
2763   const char* szType = argv[1];
2764   if      (strcmp(szType, "NONE"    ) == 0) aFillType = Aspect_FM_NONE;
2765   else if (strcmp(szType, "CENTERED") == 0) aFillType = Aspect_FM_CENTERED;
2766   else if (strcmp(szType, "TILED"   ) == 0) aFillType = Aspect_FM_TILED;
2767   else if (strcmp(szType, "STRETCH" ) == 0) aFillType = Aspect_FM_STRETCH;
2768   else
2769   {
2770     di << "Wrong fill type : " << szType << "\n";
2771     di << "Must be one of CENTERED, TILED, STRETCH, NONE\n";
2772     return 1;
2773   }
2774   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2775   V3dView->SetBgImageStyle(aFillType, Standard_True);
2776   return 0;
2777 }
2778
2779 //==============================================================================
2780 //function : VSetGradientBg
2781 //purpose  : Mount gradient background
2782 //==============================================================================
2783 static int VSetGradientBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2784 {
2785   if (argc != 8 )
2786   {
2787     di << "Usage : " << argv[0] << " R1 G1 B1 R2 G2 B2 Type : Mount gradient background\n";
2788     di << "R1,G1,B1,R2,G2,B2 = [0..255]\n";
2789     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2790     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2791     return 1;
2792   }
2793
2794   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2795   if(AISContext.IsNull())
2796   {
2797     di << "use 'vinit' command before " << argv[0] << "\n";
2798     return 1;
2799   }
2800   if (argc == 8)
2801   {
2802
2803     Standard_Real R1 = Draw::Atof(argv[1])/255.;
2804     Standard_Real G1 = Draw::Atof(argv[2])/255.;
2805     Standard_Real B1 = Draw::Atof(argv[3])/255.;
2806     Quantity_Color aColor1(R1,G1,B1,Quantity_TOC_RGB);
2807
2808     Standard_Real R2 = Draw::Atof(argv[4])/255.;
2809     Standard_Real G2 = Draw::Atof(argv[5])/255.;
2810     Standard_Real B2 = Draw::Atof(argv[6])/255.;
2811
2812     Quantity_Color aColor2(R2,G2,B2,Quantity_TOC_RGB);
2813     int aType = Draw::Atoi(argv[7]);
2814     if( aType < 0 || aType > 8 )
2815     {
2816       di << "Wrong fill type \n";
2817       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2818       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2819       return 1;
2820     }
2821
2822     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2823
2824     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2825     V3dView->SetBgGradientColors( aColor1, aColor2, aMethod, 1);
2826   }
2827
2828   return 0;
2829 }
2830
2831 //==============================================================================
2832 //function : VSetGradientBgMode
2833 //purpose  : Change gradient background fill style
2834 //==============================================================================
2835 static int VSetGradientBgMode(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2836 {
2837   if (argc != 2 )
2838   {
2839     di << "Usage : " << argv[0] << " Type : Change gradient background fill type\n";
2840     di << "Type must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2841     di << "                    5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2842     return 1;
2843   }
2844
2845   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2846   if(AISContext.IsNull())
2847   {
2848     di << "use 'vinit' command before " << argv[0] << "\n";
2849     return 1;
2850   }
2851   if (argc == 2)
2852   {
2853     int aType = Draw::Atoi(argv[1]);
2854     if( aType < 0 || aType > 8 )
2855     {
2856       di << "Wrong fill type \n";
2857       di << "Must be one of 0 = NONE, 1 = HOR, 2 = VER, 3 = DIAG1, 4 = DIAG2\n";
2858       di << "               5 = CORNER1, 6 = CORNER2, 7 = CORNER3, 8 = CORNER4\n";
2859       return 1;
2860     }
2861
2862     Aspect_GradientFillMethod aMethod = Aspect_GradientFillMethod(aType);
2863
2864     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2865     V3dView->SetBgGradientStyle( aMethod, 1 );
2866   }
2867
2868   return 0;
2869 }
2870
2871 //==============================================================================
2872 //function : VSetColorBg
2873 //purpose  : Set color background
2874 //==============================================================================
2875 static int VSetColorBg(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2876 {
2877   if (argc != 4 )
2878   {
2879     di << "Usage : " << argv[0] << " R G B : Set color background\n";
2880     di << "R,G,B = [0..255]\n";
2881     return 1;
2882   }
2883
2884   Handle(AIS_InteractiveContext) AISContext = ViewerTest::GetAISContext();
2885   if(AISContext.IsNull())
2886   {
2887     di << "use 'vinit' command before " << argv[0] << "\n";
2888     return 1;
2889   }
2890   if (argc == 4)
2891   {
2892
2893     Standard_Real R = Draw::Atof(argv[1])/255.;
2894     Standard_Real G = Draw::Atof(argv[2])/255.;
2895     Standard_Real B = Draw::Atof(argv[3])/255.;
2896     Quantity_Color aColor(R,G,B,Quantity_TOC_RGB);
2897
2898     Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2899     V3dView->SetBackgroundColor( aColor );
2900     V3dView->Update();
2901   }
2902
2903   return 0;
2904 }
2905
2906 //==============================================================================
2907 //function : VSetDefaultBg
2908 //purpose  : Set default viewer background fill color
2909 //==============================================================================
2910 static int VSetDefaultBg (Draw_Interpretor& theDI, Standard_Integer theArgNb, const char** theArgVec)
2911 {
2912   if (theArgNb != 4
2913    && theArgNb != 8)
2914   {
2915     std::cout << "Error: wrong syntax! See usage:\n";
2916     theDI.PrintHelp (theArgVec[0]);
2917     return 1;
2918   }
2919
2920   ViewerTest_DefaultBackground.FillMethod =
2921     theArgNb == 4 ? Aspect_GFM_NONE
2922                   : (Aspect_GradientFillMethod) Draw::Atoi (theArgVec[7]);
2923
2924   if (theArgNb == 4)
2925   {
2926     Standard_Real R = Draw::Atof (theArgVec[1]) / 255.;
2927     Standard_Real G = Draw::Atof (theArgVec[2]) / 255.;
2928     Standard_Real B = Draw::Atof (theArgVec[3]) / 255.;
2929     ViewerTest_DefaultBackground.FlatColor.SetValues (R, G, B, Quantity_TOC_RGB);
2930   }
2931   else
2932   {
2933     Standard_Real R1 = Draw::Atof (theArgVec[1]) / 255.;
2934     Standard_Real G1 = Draw::Atof (theArgVec[2]) / 255.;
2935     Standard_Real B1 = Draw::Atof (theArgVec[3]) / 255.;
2936     ViewerTest_DefaultBackground.GradientColor1.SetValues (R1, G1, B1, Quantity_TOC_RGB);
2937
2938     Standard_Real R2 = Draw::Atof (theArgVec[4]) / 255.;
2939     Standard_Real G2 = Draw::Atof (theArgVec[5]) / 255.;
2940     Standard_Real B2 = Draw::Atof (theArgVec[6]) / 255.;
2941     ViewerTest_DefaultBackground.GradientColor2.SetValues (R2, G2, B2, Quantity_TOC_RGB);
2942   }
2943
2944   for (NCollection_DoubleMap<TCollection_AsciiString, Handle(AIS_InteractiveContext)>::Iterator
2945        anIter (ViewerTest_myContexts); anIter.More(); anIter.Next())
2946   {
2947     const Handle(V3d_Viewer)& aViewer = anIter.Value()->CurrentViewer();
2948     aViewer->SetDefaultBackgroundColor (ViewerTest_DefaultBackground.FlatColor);
2949     aViewer->SetDefaultBgGradientColors (ViewerTest_DefaultBackground.GradientColor1,
2950                                          ViewerTest_DefaultBackground.GradientColor2,
2951                                          ViewerTest_DefaultBackground.FillMethod);
2952   }
2953
2954   return 0;
2955 }
2956
2957 //==============================================================================
2958 //function : VScale
2959 //purpose  : View Scaling
2960 //==============================================================================
2961
2962 static int VScale(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
2963 {
2964   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
2965   if ( V3dView.IsNull() ) return 1;
2966
2967   if ( argc != 4 ) {
2968     di << argv[0] << "Invalid number of arguments\n";
2969     return 1;
2970   }
2971   V3dView->SetAxialScale( Draw::Atof(argv[1]),  Draw::Atof(argv[2]),  Draw::Atof(argv[3]) );
2972   return 0;
2973 }
2974 //==============================================================================
2975 //function : VZBuffTrihedron
2976 //purpose  :
2977 //==============================================================================
2978
2979 static int VZBuffTrihedron (Draw_Interpretor& /*theDI*/,
2980                             Standard_Integer  theArgNb,
2981                             const char**      theArgVec)
2982 {
2983   Handle(V3d_View) aView = ViewerTest::CurrentView();
2984   if (aView.IsNull())
2985   {
2986     std::cout << "Error: no active viewer!\n";
2987     return 1;
2988   }
2989
2990   ViewerTest_AutoUpdater anUpdateTool (ViewerTest::GetAISContext(), aView);
2991
2992   Aspect_TypeOfTriedronPosition aPosition     = Aspect_TOTP_LEFT_LOWER;
2993   V3d_TypeOfVisualization       aVisType      = V3d_ZBUFFER;
2994   Quantity_Color                aLabelsColor  = Quantity_NOC_WHITE;
2995   Quantity_Color                anArrowColorX = Quantity_NOC_RED;
2996   Quantity_Color                anArrowColorY = Quantity_NOC_GREEN;
2997   Quantity_Color                anArrowColorZ = Quantity_NOC_BLUE1;
2998   Standard_Real                 aScale        = 0.1;
2999   Standard_Real                 aSizeRatio    = 0.8;
3000   Standard_Real                 anArrowDiam   = 0.05;
3001   Standard_Integer              aNbFacets     = 12;
3002   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3003   {
3004     Standard_CString        anArg = theArgVec[anArgIter];
3005     TCollection_AsciiString aFlag (anArg);
3006     aFlag.LowerCase();
3007     if (anUpdateTool.parseRedrawMode (aFlag))
3008     {
3009       continue;
3010     }
3011     else if (aFlag == "-on")
3012     {
3013       continue;
3014     }
3015     else if (aFlag == "-off")
3016     {
3017       aView->TriedronErase();
3018       return 0;
3019     }
3020     else if (aFlag == "-pos"
3021           || aFlag == "-position"
3022           || aFlag == "-corner")
3023     {
3024       if (++anArgIter >= theArgNb)
3025       {
3026         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3027         return 1;
3028       }
3029
3030       TCollection_AsciiString aPosName (theArgVec[anArgIter]);
3031       aPosName.LowerCase();
3032       if (aPosName == "center")
3033       {
3034         aPosition = Aspect_TOTP_CENTER;
3035       }
3036       else if (aPosName == "left_lower"
3037             || aPosName == "lower_left"
3038             || aPosName == "leftlower"
3039             || aPosName == "lowerleft")
3040       {
3041         aPosition = Aspect_TOTP_LEFT_LOWER;
3042       }
3043       else if (aPosName == "left_upper"
3044             || aPosName == "upper_left"
3045             || aPosName == "leftupper"
3046             || aPosName == "upperleft")
3047       {
3048         aPosition = Aspect_TOTP_LEFT_UPPER;
3049       }
3050       else if (aPosName == "right_lower"
3051             || aPosName == "lower_right"
3052             || aPosName == "rightlower"
3053             || aPosName == "lowerright")
3054       {
3055         aPosition = Aspect_TOTP_RIGHT_LOWER;
3056       }
3057       else if (aPosName == "right_upper"
3058             || aPosName == "upper_right"
3059             || aPosName == "rightupper"
3060             || aPosName == "upperright")
3061       {
3062         aPosition = Aspect_TOTP_RIGHT_UPPER;
3063       }
3064       else
3065       {
3066         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown position '" << aPosName << "'\n";
3067         return 1;
3068       }
3069     }
3070     else if (aFlag == "-type")
3071     {
3072       if (++anArgIter >= theArgNb)
3073       {
3074         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3075         return 1;
3076       }
3077
3078       TCollection_AsciiString aTypeName (theArgVec[anArgIter]);
3079       aTypeName.LowerCase();
3080       if (aTypeName == "wireframe"
3081        || aTypeName == "wire")
3082       {
3083         aVisType = V3d_WIREFRAME;
3084       }
3085       else if (aTypeName == "zbuffer"
3086             || aTypeName == "shaded")
3087       {
3088         aVisType = V3d_ZBUFFER;
3089       }
3090       else
3091       {
3092         std::cerr << "Error: wrong syntax at '" << anArg << "' - unknown type '" << aTypeName << "'\n";
3093       }
3094     }
3095     else if (aFlag == "-scale")
3096     {
3097       if (++anArgIter >= theArgNb)
3098       {
3099         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3100         return 1;
3101       }
3102
3103       aScale = Draw::Atof (theArgVec[anArgIter]);
3104     }
3105     else if (aFlag == "-size"
3106           || aFlag == "-sizeratio")
3107     {
3108       if (++anArgIter >= theArgNb)
3109       {
3110         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3111         return 1;
3112       }
3113
3114       aSizeRatio = Draw::Atof (theArgVec[anArgIter]);
3115     }
3116     else if (aFlag == "-arrowdiam"
3117           || aFlag == "-arrowdiameter")
3118     {
3119       if (++anArgIter >= theArgNb)
3120       {
3121         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3122         return 1;
3123       }
3124
3125       anArrowDiam = Draw::Atof (theArgVec[anArgIter]);
3126     }
3127     else if (aFlag == "-nbfacets")
3128     {
3129       if (++anArgIter >= theArgNb)
3130       {
3131         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3132         return 1;
3133       }
3134
3135       aNbFacets = Draw::Atoi (theArgVec[anArgIter]);
3136     }
3137     else if (aFlag == "-colorlabel"
3138           || aFlag == "-colorlabels")
3139     {
3140       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3141                                                            theArgVec + anArgIter + 1,
3142                                                            aLabelsColor);
3143       if (aNbParsed == 0)
3144       {
3145         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3146         return 1;
3147       }
3148       anArgIter += aNbParsed;
3149     }
3150     else if (aFlag == "-colorarrowx")
3151     {
3152       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3153                                                            theArgVec + anArgIter + 1,
3154                                                            anArrowColorX);
3155       if (aNbParsed == 0)
3156       {
3157         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3158         return 1;
3159       }
3160       anArgIter += aNbParsed;
3161     }
3162     else if (aFlag == "-colorarrowy")
3163     {
3164       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3165                                                            theArgVec + anArgIter + 1,
3166                                                            anArrowColorY);
3167       if (aNbParsed == 0)
3168       {
3169         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3170         return 1;
3171       }
3172       anArgIter += aNbParsed;
3173     }
3174     else if (aFlag == "-colorarrowz")
3175     {
3176       Standard_Integer aNbParsed = ViewerTest::ParseColor (theArgNb  - anArgIter - 1,
3177                                                            theArgVec + anArgIter + 1,
3178                                                            anArrowColorZ);
3179       if (aNbParsed == 0)
3180       {
3181         std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3182         return 1;
3183       }
3184       anArgIter += aNbParsed;
3185     }
3186     else
3187     {
3188       std::cerr << "Error: wrong syntax at '" << anArg << "'\n";
3189       return 1;
3190     }
3191   }
3192
3193   aView->ZBufferTriedronSetup (anArrowColorX.Name(), anArrowColorY.Name(), anArrowColorZ.Name(),
3194                                aSizeRatio, anArrowDiam, aNbFacets);
3195   aView->TriedronDisplay (aPosition, aLabelsColor.Name(), aScale, aVisType);
3196   aView->ZFitAll();
3197   return 0;
3198 }
3199
3200 //==============================================================================
3201 //function : VRotate
3202 //purpose  : Camera Rotating
3203 //==============================================================================
3204
3205 static int VRotate (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgVec)
3206 {
3207   Handle(V3d_View) aView = ViewerTest::CurrentView();
3208   if (aView.IsNull())
3209   {
3210     std::cout << "No active view!\n";
3211     return 1;
3212   }
3213
3214   Standard_Boolean hasFlags = Standard_False;
3215   for (Standard_Integer anArgIter = 1; anArgIter < theArgNb; ++anArgIter)
3216   {
3217     Standard_CString        anArg (theArgVec[anArgIter]);
3218     TCollection_AsciiString aFlag (anArg);
3219     aFlag.LowerCase();
3220     if (aFlag == "-mousestart"
3221      || aFlag == "-mousefrom")
3222     {
3223       hasFlags = Standard_True;
3224       if (anArgIter + 2 >= theArgNb)
3225       {
3226         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3227         return 1;
3228       }
3229
3230       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3231       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3232       aView->StartRotation (anX, anY);
3233     }
3234     else if (aFlag == "-mousemove")
3235     {
3236       hasFlags = Standard_True;
3237       if (anArgIter + 2 >= theArgNb)
3238       {
3239         std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3240         return 1;
3241       }
3242
3243       Standard_Integer anX = Draw::Atoi (theArgVec[++anArgIter]);
3244       Standard_Integer anY = Draw::Atoi (theArgVec[++anArgIter]);
3245       aView->Rotation (anX, anY);
3246     }
3247     else if (theArgNb != 4
3248           && theArgNb != 7)
3249     {
3250       std::cout << "Error: wrong syntax at '" << anArg << "'\n";
3251       return 1;
3252     }
3253   }
3254
3255   if (hasFlags)
3256   {
3257     return 0;
3258   }
3259   else if (theArgNb == 4)
3260   {
3261     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3262     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3263     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3264     aView->Rotate (anAX, anAY, anAZ);
3265     return 0;
3266   }
3267   else if (theArgNb == 7)
3268   {
3269     Standard_Real anAX = Draw::Atof (theArgVec[1]);
3270     Standard_Real anAY = Draw::Atof (theArgVec[2]);
3271     Standard_Real anAZ = Draw::Atof (theArgVec[3]);
3272
3273     Standard_Real anX = Draw::Atof (theArgVec[4]);
3274     Standard_Real anY = Draw::Atof (theArgVec[5]);
3275     Standard_Real anZ = Draw::Atof (theArgVec[6]);
3276
3277     aView->Rotate (anAX, anAY, anAZ, anX, anY, anZ);
3278     return 0;
3279   }
3280
3281   std::cout << "Error: Invalid number of arguments\n";
3282   return 1;
3283 }
3284
3285 //==============================================================================
3286 //function : VZoom
3287 //purpose  : View zoom in / out (relative to current zoom)
3288 //==============================================================================
3289
3290 static int VZoom( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3291   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3292   if ( V3dView.IsNull() ) {
3293     return 1;
3294   }
3295
3296   if ( argc == 2 ) {
3297     Standard_Real coef = Draw::Atof(argv[1]);
3298     if ( coef <= 0.0 ) {
3299       di << argv[1] << "Invalid value\n";
3300       return 1;
3301     }
3302     V3dView->SetZoom( Draw::Atof(argv[1]) );
3303     return 0;
3304   } else {
3305     di << argv[0] << " Invalid number of arguments\n";
3306     return 1;
3307   }
3308 }
3309
3310 //==============================================================================
3311 //function : VPan
3312 //purpose  : View panning (in pixels)
3313 //==============================================================================
3314
3315 static int VPan( Draw_Interpretor& di, Standard_Integer argc, const char** argv ) {
3316   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3317   if ( V3dView.IsNull() ) return 1;
3318
3319   if ( argc == 3 ) {
3320     V3dView->Pan( Draw::Atoi(argv[1]), Draw::Atoi(argv[2]) );
3321     return 0;
3322   } else {
3323     di << argv[0] << " Invalid number of arguments\n";
3324     return 1;
3325   }
3326 }
3327
3328 //==============================================================================
3329 //function : VPlace
3330 //purpose  : Place the point (in pixels) at the center of the window
3331 //==============================================================================
3332 static int VPlace (Draw_Interpretor& /*theDi*/, Standard_Integer theArgNb, const char** theArgs)
3333 {
3334   Handle(V3d_View) aView = ViewerTest::CurrentView();
3335   if (aView.IsNull())
3336   {
3337     std::cerr << theArgs[0] << "Error: no active view." << std::endl;
3338     return 1;
3339   }
3340
3341   if (theArgNb != 3)
3342   {
3343     std::cerr << theArgs[0] << "Error: invalid number of arguments." << std::endl;
3344     return 1;
3345   }
3346
3347   aView->Place (Draw::Atoi (theArgs[1]), Draw::Atoi (theArgs[2]), aView->Scale());
3348
3349   return 0;
3350 }
3351
3352 //==============================================================================
3353 //function : VExport
3354 //purpose  : Export the view to a vector graphic format (PS, EMF, PDF)
3355 //==============================================================================
3356
3357 static int VExport(Draw_Interpretor& di, Standard_Integer argc, const char** argv)
3358 {
3359   Handle(V3d_View) V3dView = ViewerTest::CurrentView();
3360   if (V3dView.IsNull())
3361     return 1;
3362
3363   if (argc == 1)
3364   {
3365     std::cout << "Usage: " << argv[0] << " Filename [Format]\n";
3366     return 1;
3367   }
3368
3369   Graphic3d_ExportFormat anExpFormat = Graphic3d_EF_PDF;
3370   TCollection_AsciiString aFormatStr;
3371
3372   TCollection_AsciiString aFileName (argv[1]);
3373   Standard_Integer aLen = aFileName.Length();
3374
3375   if (argc > 2)
3376   {
3377     aFormatStr = TCollection_AsciiString (argv[2]);
3378   }
3379   else if (aLen >= 4)
3380   {
3381     if (aFileName.Value (aLen - 2) == '.')
3382     {
3383       aFormatStr = aFileName.ToCString() + aLen - 2;
3384     }
3385     else if (aFileName.Value (aLen - 3) == '.')
3386     {
3387       aFormatStr = aFileName.ToCString() + aLen - 3;
3388     }
3389     else
3390     {
3391       std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3392       return 1;
3393     }
3394   }
3395   else
3396   {
3397     std::cout << "Export format couln't be detected from filename '" << argv[1] << "'\n";
3398     return 1;
3399   }
3400
3401   aFormatStr.UpperCase();
3402   if (aFormatStr == "PS")
3403     anExpFormat = Graphic3d_EF_PostScript;
3404   else if (aFormatStr == "EPS")
3405     anExpFormat = Graphic3d_EF_EnhPostScript;
3406   else if (aFormatStr == "TEX")
3407     anExpFormat = Graphic3d_EF_TEX;
3408   else if (aFormatStr == "PDF")
3409     anExpFormat = Graphic3d_EF_PDF;
3410   else if (aFormatStr == "SVG")
3411     anExpFormat = Graphic3d_EF_SVG;
3412   else if (aFormatStr == "PGF")
3413     anExpFormat = Graphic3d_EF_PGF;
3414   else if (aFormatStr == "EMF")
3415     anExpFormat = Graphic3d_EF_EMF;
3416   else
3417   {
3418     std::cout << "Invalid export format '" << aFormatStr << "'\n";
3419     return 1;
3420   }
3421
3422   try
3423   {
3424     if (!V3dView->Export (argv[1], anExpFormat))
3425     {
3426       di << "Error: export of image to " << aFormatStr << " failed!\n";
3427     }
3428   }
3429   catch (Standard_Failure)
3430   {
3431     di << "Error: export of image to " << aFormatStr << " failed";
3432     di << " (exception: " << Standard_Failure::Caught()->GetMessageString() << ")";
3433   }
3434   return 0;
3435 }
3436
3437 //==============================================================================
3438 //function : VColorScale
3439 //purpose  : representation color scale
3440 //==============================================================================
3441
3442 static Standard_Boolean checkColor (const TCollection_AsciiString& theRed,
3443                                     const TCollection_AsciiString& theGreen,
3444                                     const TCollection_AsciiString& theBlue,
3445                                                     Standard_Real& theRedValue,
3446                                                     Standard_Real& theGreenValue,
3447                                                     Standard_Real& theBlueValue)
3448 {
3449   if (!theRed.IsRealValue()
3450    || !theGreen.IsRealValue()
3451    || !theBlue.IsRealValue())
3452   {
3453     std::cout << "Error: RGB color values should be real!\n";
3454     return Standard_True;
3455   }
3456   theRedValue = theRed    .RealValue();
3457   theGreenValue = theGreen.RealValue();
3458   theBlueValue = theBlue  .RealValue();
3459   if (theRedValue < 0.0 || theRedValue > 1.0
3460    || theGreenValue < 0.0 || theGreenValue > 1.0
3461    || theBlueValue < 0.0 || theBlueValue > 1.0)
3462   {
3463     std::cout << "Error: RGB color values should be within range 0..1!\n";
3464     return Standard_True;
3465   }
3466   return Standard_False;
3467 }
3468
3469 static int VColorScale (Draw_Interpretor& theDI,
3470                         Standard_Integer  theArgNb,
3471                         const char**      theArgVec)
3472 {
3473   Handle(AIS_InteractiveContext) aContext = ViewerTest::GetAISContext();
3474   Handle(V3d_View)               aView    = ViewerTest::CurrentView();
3475   if (aContext.IsNull())
3476   {
3477     std::cout << "Error: no active view!\n";
3478     return 1;
3479   }
3480   if (theArgNb <= 1)
3481   {
3482     std::cout << "Error: wrong syntax at command '" << theArgVec[0] << "'!\n";
3483     return 1;
3484   }
3485
3486   Handle(AIS_ColorScale) aCS;