]> SALOME platform Git repositories - modules/gui.git/blob - src/SALOME_PY/SalomePy.cxx
Salome HOME
Replace deprecated WNT macro definition by WIN32.
[modules/gui.git] / src / SALOME_PY / SalomePy.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D, OPEN CASCADE
2 //
3 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
5 //
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
10 //
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14 // Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 //
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
21 //
22
23 //  SALOME SALOME_PY : binding of VTK graphics and Python
24 //  File   : SalomePy.cxx
25 //  Author : Paul RASCLE, EDF
26 //
27 #ifdef WIN32
28 // E.A. : On windows with python 2.6, there is a conflict
29 // E.A. : between pymath.h and Standard_math.h which define
30 // E.A. : some same symbols : acosh, asinh, ...
31 #include <Standard_math.hxx>
32 #include <pymath.h>
33 #endif
34
35 #include <Python.h>
36 #include <vtkPythonUtil.h>
37
38 #include <vtkVersion.h>
39 #include <vtkRenderer.h>
40 #include <vtkRenderWindow.h>
41 #include <vtkRenderWindowInteractor.h>
42
43 #include <SALOME_Event.h>
44
45 #include <SUIT_Session.h>
46 #include <LightApp_Application.h>
47 #include <LightApp_Study.h>
48
49 #include <SVTK_ViewManager.h>
50 #include <SVTK_ViewWindow.h>
51
52 #define VTK_XVERSION (VTK_MAJOR_VERSION*10000+VTK_MINOR_VERSION*100+VTK_BUILD_VERSION)
53
54 /*!
55   \brief Python wrappings for VTK viewer of the SALOME desktop.
56
57   All methods are implemented using Event mechanism. The module
58   provides the following functions:
59   - getRenderer()
60   - getRenderWindow()
61   - getRenderWindowInteractor()
62   - showTrihedron()
63   - fitAll()
64   - setView()
65   - resetView()
66
67   Usage in Python:
68   \code
69   import SalomePy
70   renderer = SalomePy.getRenderer()     # get VTK renderer
71   window   = SalomePy.getRenderWindow() # get render window
72   \endcode
73
74   The methods getRenderer(), getRenderWindow() and getRenderWindowInteractor()
75   open new VTK viewer if there is no one opened.
76   In case of any error these methods return None object to the Python.
77 */
78
79 #define PUBLISH_ENUM(i)                              \
80 {                                                    \
81   PyObject *w;                                       \
82   int rc;                                            \
83   if ( ( w = PyInt_FromLong( i ) ) == NULL ) return; \
84   rc = PyDict_SetItemString( aModuleDict, #i, w );   \
85   Py_DECREF( w );                                    \
86   if ( rc < 0 ) return;                              \
87 }
88
89 //! View operation type
90 enum {
91   ViewFront,     //!< front view
92   ViewBack,      //!< back view
93   ViewTop,       //!< top view
94   ViewBottom,    //!< bottom view
95   ViewRight,     //!< right view
96   ViewLeft       //!< left view
97 };
98
99 /*!
100   \brief Get Python class object by name
101   \internal
102   \param theClassName Python class name
103   \return Python class object or None object if class is not found
104 */
105 static PyObject* GetPyClass( const char* theClassName ) 
106 {
107   static PyObject* aVTKModule = 0;
108   PyObject* aPyClass = 0;
109   if( !aVTKModule ) {
110 #if VTK_XVERSION < 30000
111     aVTKModule = PyImport_ImportModule( "libVTKGraphicsPython" ); 
112 #elif VTK_XVERSION < 50700
113     aVTKModule = PyImport_ImportModule( "vtk.libvtkRenderingPython" ); 
114 #elif VTK_XVERSION < 60000
115     aVTKModule = PyImport_ImportModule( "vtkRenderingPython" ); 
116 #else
117     aVTKModule = PyImport_ImportModule( "vtkRenderingCorePython" ); 
118 #endif
119     if( PyErr_Occurred() ) {
120       PyErr_Print();
121     }
122   }
123   if ( aVTKModule ) {
124     PyObject* aVTKDict = PyModule_GetDict( aVTKModule );
125     aPyClass = PyDict_GetItemString(aVTKDict, const_cast<char*>( theClassName ) );
126   }
127   return aPyClass;
128 }
129
130 /*!
131   \brief VTK window find/create mode
132   \internal
133 */
134 enum { 
135   __Find,          // try to find VTK window; if not found, do nothing
136   __FindOrCreate,  // try to find VTK window; if not found, create new one
137   __Create };      // create new VTK window
138
139 /*!
140   \brief Find or create VTK window.
141   \internal
142   \param toCreate window find/create mode
143   \return VTK window pointer or 0 if it could not be found/created
144 */
145 static SVTK_ViewWindow* GetVTKViewWindow( int toCreate = __FindOrCreate ) {
146   SVTK_ViewWindow* aVW = 0;
147   if ( SUIT_Session::session() ) {
148     // get application
149     LightApp_Application* anApp = dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() );
150     if ( anApp ) {
151       // get active study
152       LightApp_Study* aStudy = dynamic_cast<LightApp_Study*>( anApp->activeStudy() );
153       if ( aStudy ) {
154         // find or create VTK view manager
155         if ( toCreate == __Create ) {
156           SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->createViewManager( "VTKViewer" ) );
157           if ( aVM ) {
158             aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
159             if ( !aVW )
160               aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->createViewWindow() );
161             // VSR : When new view window is created it can be not active yet at this moment,
162             // so the following is a some workaround
163             if ( !aVW && !aVM->getViews().isEmpty() )
164               aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
165           }
166         }
167         else {
168           SVTK_ViewManager* aVM = dynamic_cast<SVTK_ViewManager*>( anApp->getViewManager( "VTKViewer", toCreate == __FindOrCreate ) );
169           if ( aVM ) {
170             aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getActiveView() );
171             // VSR : When new view window is created it can be not active yet at this moment,
172             // so the following is a some workaround
173             if ( !aVW && !aVM->getViews().isEmpty() )
174               aVW = dynamic_cast<SVTK_ViewWindow*>( aVM->getViews()[0] );
175           }
176         }
177       }
178     }
179   }
180   return aVW;
181 }
182
183 /*!
184   \fn PyObject* getRenderer( int toCreate = 0 );
185   \brief Get VTK renderer (vtkRenderer).
186   
187   If \a toCreate parameter is 0 (by default) the function tries to find
188   and reuse existing VTK window; if it is not found, the new VTK window
189   is opened.
190
191   If \a toCreate parameter is non-zero, the function always creates
192   new VTK window.
193
194   If VTK window could not be found and or created, the None Python object
195   is returned.
196
197   \param toCreate window creation mode
198   \return VTK window renderer object
199 */
200
201 class TGetRendererEvent: public SALOME_Event
202 {
203 public:
204   typedef PyObject* TResult;
205   TResult myResult;
206   int     myCreate;
207   TGetRendererEvent( bool toCreate )
208     : myResult( Py_None ), myCreate( toCreate ) {}
209   virtual void Execute()
210   {
211     PyObject* aPyClass = ::GetPyClass( "vtkRenderer" );
212     SVTK_ViewWindow* aVTKViewWindow = 
213       ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
214     if( aVTKViewWindow && aPyClass ) {
215       vtkRenderer* aVTKObject = aVTKViewWindow->getRenderer();
216 #if VTK_XVERSION < 50700
217       myResult = PyVTKObject_New( aPyClass, aVTKObject );
218 #else
219       myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
220 #endif
221     }
222   }
223 };
224
225 extern "C" PyObject* libSalomePy_getRenderer( PyObject* self, PyObject* args )
226 {
227   PyObject* aResult = Py_None;
228   int toCreate = 0;
229   if ( !PyArg_ParseTuple( args, "|i:getRenderer", &toCreate ) )
230     PyErr_Print();
231   else
232     aResult = ProcessEvent( new TGetRendererEvent( toCreate ) );
233   return aResult;
234 }
235
236 /*!
237   \fn PyObject* getRenderWindow( int toCreate = 0 );
238   \brief Get VTK render window (vtkRenderWindow).
239   
240   If \a toCreate parameter is 0 (by default) the function tries to find 
241   and reuse existing VTK window; if it is not found, the new VTK window
242   is opened.
243
244   If \a toCreate parameter is non-zero, the function always creates
245   new VTK window.
246
247   If VTK window could not be found and or created, the None Python object
248   is returned.
249
250   \param toCreate window creation mode
251   \return VTK window render window object
252 */
253
254 class TGetRenderWindowEvent: public SALOME_Event
255 {
256 public:
257   typedef PyObject* TResult;
258   TResult myResult;
259   int     myCreate;
260   TGetRenderWindowEvent( bool toCreate )
261     : myResult( Py_None ), myCreate( toCreate ) {}
262   virtual void Execute()
263   {
264     PyObject* aPyClass = ::GetPyClass( "vtkRenderWindow" );
265     SVTK_ViewWindow* aVTKViewWindow = 
266       ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
267     if( aVTKViewWindow && aPyClass ) {
268       vtkRenderWindow* aVTKObject = aVTKViewWindow->getRenderWindow();
269 #if VTK_XVERSION < 50700
270       myResult = PyVTKObject_New( aPyClass, aVTKObject );
271 #else
272       myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
273 #endif
274     }
275   }
276 };
277
278 extern "C" PyObject* libSalomePy_getRenderWindow( PyObject* self, PyObject* args )
279 {
280   PyObject* aResult = Py_None;
281   int toCreate = 0;
282   if ( !PyArg_ParseTuple( args, "|i:getRenderWindow", &toCreate ) )
283     PyErr_Print();
284   else
285     aResult = ProcessEvent( new TGetRenderWindowEvent( toCreate ) );
286   return aResult;
287 }
288
289 /*!
290   \fn PyObject* getRenderWindowInteractor( int toCreate = 0 );
291   \brief Get VTK render window interactor (getRenderWindowInteractor).
292   
293   If \a toCreate parameter is 0 (by default) the function tries to find 
294   and reuse existing VTK window; if it is not found, the new VTK window
295   is opened.
296
297   If \a toCreate parameter is non-zero, the function always creates
298   new VTK window.
299
300   If VTK window could not be found and or created, the None Python object
301   is returned.
302
303   \param toCreate window creation mode
304   \return VTK window render window interactor object
305 */
306
307 class TGetRenderWindowInteractorEvent: public SALOME_Event
308 {
309 public:
310   typedef PyObject* TResult;
311   TResult myResult;
312   int     myCreate;
313   TGetRenderWindowInteractorEvent( bool toCreate )
314     : myResult( Py_None ), myCreate( toCreate ) {}
315   virtual void Execute()
316   {
317     PyObject* aPyClass = ::GetPyClass( "vtkRenderWindowInteractor" );
318     SVTK_ViewWindow* aVTKViewWindow = 
319       ::GetVTKViewWindow( myCreate ? __Create : __FindOrCreate );
320     if( aVTKViewWindow && aPyClass ) {
321       vtkRenderWindowInteractor* aVTKObject = aVTKViewWindow->getInteractor();
322 #if VTK_XVERSION < 50700
323       myResult = PyVTKObject_New( aPyClass, aVTKObject );
324 #else
325       myResult = PyVTKObject_New( aPyClass, NULL, aVTKObject );
326 #endif
327     }
328   }
329 };
330
331 extern "C" PyObject* libSalomePy_getRenderWindowInteractor( PyObject* self, PyObject* args )
332 {
333   PyObject* aResult = Py_None;
334   int toCreate = 0;
335   if ( !PyArg_ParseTuple( args, "|i:getRenderWindowInteractor", &toCreate ) )
336     PyErr_Print();
337   else
338     aResult = ProcessEvent( new TGetRenderWindowInteractorEvent( toCreate ) );
339   return aResult;
340 }
341
342 /*!
343   \fn PyObject* showTrihedron( int show );
344   \brief Show/hide trihedron in the current VTK viewer.
345
346   If there is no active VTK viewer, nothing happens.
347   
348   \param show new trihedron visibility state
349   \return nothing (Py_None)
350 */
351
352 extern "C" PyObject* libSalomePy_showTrihedron( PyObject* self, PyObject* args )
353 {
354   class TEvent: public SALOME_Event
355   {
356   public:
357     int myShow;
358     TEvent( int bShow )
359       : myShow( bShow ) {}
360     virtual void Execute()
361     {
362       if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
363         if ( aVTKViewWindow->isTrihedronDisplayed() != myShow )
364           aVTKViewWindow->onViewTrihedron();
365       }
366     }
367   };
368   
369   PyObject* aResult = Py_None;
370   int bShow = 0;
371   if ( !PyArg_ParseTuple( args, "i:showTrihedron", &bShow ) )
372     PyErr_Print();
373   else
374     ProcessVoidEvent( new TEvent( bShow ) );
375   return aResult;
376 }
377
378 /*!
379   \fn PyObject* fitAll();
380   \brief Fit all the contents in the current VTK viewer.
381
382   If there is no active VTK viewer, nothing happens.
383
384   \return nothing (Py_None)
385 */
386
387 extern "C" PyObject* libSalomePy_fitAll( PyObject* self, PyObject* args )
388 {
389   class TEvent: public SALOME_Event
390   {
391   public:
392     TEvent() {}
393     virtual void Execute()
394     {
395       if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
396         aVTKViewWindow->onFitAll();
397       }
398     }
399   };
400   
401   ProcessVoidEvent( new TEvent() );
402   return Py_None;
403 }
404
405 /*!
406   \fn PyObject* setView( int type );
407   \brief Set view type for the current VTK viewer.
408
409   If there is no active VTK viewer, nothing happens.
410   
411   \param type view type
412   \return nothing (Py_None)
413 */
414
415 extern "C" PyObject* libSalomePy_setView( PyObject* self, PyObject* args )
416 {
417   class TEvent: public SALOME_Event
418   {
419   public:
420     long myType;
421     TEvent( long type ) : myType( type) {}
422     virtual void Execute()
423     {
424       if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
425         switch( myType ) {
426         case ViewFront:
427           aVTKViewWindow->onFrontView();  break;
428         case ViewBack:
429           aVTKViewWindow->onBackView();   break;
430         case ViewTop:
431           aVTKViewWindow->onTopView();    break;
432         case ViewBottom:
433           aVTKViewWindow->onBottomView(); break;
434         case ViewRight:
435           aVTKViewWindow->onRightView();  break;
436         case ViewLeft:
437           aVTKViewWindow->onLeftView();   break;
438         default:
439           PyErr_Format(PyExc_ValueError,"setView%: wrong parameter value; must be between %d and %d", ViewFront, ViewLeft );
440           break;
441         }
442       }
443     }
444   };
445   
446   long type = -1;
447   if ( !PyArg_ParseTuple( args, "l:setView", &type ) )
448     PyErr_Print();
449   else {
450     ProcessVoidEvent( new TEvent( type ) );
451     if( PyErr_Occurred() )
452       PyErr_Print();
453   }
454   return Py_None;
455 }
456
457 /*!
458   \fn PyObject* resetView();
459   \brief Reset contents of the current VTK viewer.
460
461   If there is no active VTK viewer, nothing happens.
462   
463   \return nothing (Py_None)
464 */
465
466 extern "C" PyObject* libSalomePy_resetView( PyObject* self, PyObject* args )
467 {
468   class TEvent: public SALOME_Event
469   {
470   public:
471     TEvent() {}
472     virtual void Execute()
473     {
474       if( SVTK_ViewWindow* aVTKViewWindow = GetVTKViewWindow( __Find ) ) {
475         aVTKViewWindow->onResetView();
476       }
477     }
478   };
479   
480   ProcessVoidEvent( new TEvent() );
481   return Py_None;
482 }
483
484 static PyMethodDef Module_Methods[] = 
485 {
486   { "getRenderer",               libSalomePy_getRenderer,               METH_VARARGS },
487   { "getRenderWindow",           libSalomePy_getRenderWindow,           METH_VARARGS },
488   { "getRenderWindowInteractor", libSalomePy_getRenderWindowInteractor, METH_VARARGS },
489   { "showTrihedron",             libSalomePy_showTrihedron,             METH_VARARGS },
490   { "fitAll",                    libSalomePy_fitAll,                    METH_NOARGS  },
491   { "setView",                   libSalomePy_setView,                   METH_VARARGS },
492   { "resetView",                 libSalomePy_resetView,                 METH_NOARGS  },
493   { NULL, NULL }
494 };
495
496 /*!
497   \brief Python module initialization.
498   \internal
499 */
500 extern "C" void initlibSalomePy()
501 {
502   static char* modulename = (char*)"libSalomePy";
503
504   // init module
505   PyObject* aModule = Py_InitModule( modulename, Module_Methods );
506   if( PyErr_Occurred() ) {
507     PyErr_Print();
508     return;
509   }
510
511   // get module's dictionary
512   PyObject *aModuleDict = PyModule_GetDict( aModule );
513   if ( aModuleDict == NULL )
514     return;
515
516   // export View type enumeration
517   PUBLISH_ENUM( ViewFront );
518   PUBLISH_ENUM( ViewBack );
519   PUBLISH_ENUM( ViewTop );
520   PUBLISH_ENUM( ViewBottom );
521   PUBLISH_ENUM( ViewRight );
522   PUBLISH_ENUM( ViewLeft );
523 }