]> Creatis software - cpPlugins.git/blob - lib/cpExtensions/Interaction/BaseInteractorStyle.cxx
Merge branch 'master' of ssh://git.creatis.insa-lyon.fr/cpPlugins
[cpPlugins.git] / lib / cpExtensions / Interaction / BaseInteractorStyle.cxx
1 #include <cpExtensions/Interaction/BaseInteractorStyle.h>
2
3 #include <cmath>
4
5 #include <vtkCallbackCommand.h>
6 #include <vtkCamera.h>
7 #include <vtkRenderer.h>
8 #include <vtkRenderWindowInteractor.h>
9
10 // -------------------------------------------------------------------------
11 long cpExtensions::Interaction::BaseInteractorStyle::_TMouseButtonEvent::
12 MaxDoubleClick = 350; // ms
13
14 // -------------------------------------------------------------------------
15 void cpExtensions::Interaction::BaseInteractorStyle::
16 SetSetDoubleClickDelay( long delay )
17 {
18   Self::_TMouseButtonEvent::MaxDoubleClick = delay;
19 }
20
21 // -------------------------------------------------------------------------
22 void cpExtensions::Interaction::BaseInteractorStyle::
23 DelegateTDxEvent( unsigned long event, void* calldata )
24 {
25   // TODO
26   std::cerr << "No TDx support at this time!" << std::endl;
27   std::exit( 1 );
28 }
29
30 // -------------------------------------------------------------------------
31 void cpExtensions::Interaction::BaseInteractorStyle::
32 OnMouseMove( )
33 {
34   // Get current position on the associated actors
35   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
36   if( rwi == NULL )
37     return;
38
39   // Get modifiers
40   bool alt = ( rwi->GetAltKey( ) == 1 );
41   bool ctr = ( rwi->GetControlKey( ) == 1 );
42   bool sft = ( rwi->GetShiftKey( ) == 1 );
43   ButtonID button = this->GetButtonID( );
44
45   // Invoke possible generic events
46   if( button == Self::ButtonID_Right )
47   {
48     if( !alt && !ctr && !sft )
49     {
50       this->FindPokedRenderer(
51         rwi->GetEventPosition( )[ 0 ],
52         rwi->GetEventPosition( )[ 1 ]
53         );
54       this->Dolly( );
55
56     } // fi
57   }
58   else if( button == Self::ButtonID_Middle )
59   {
60     if( !alt && !ctr && !sft )
61     {
62       this->FindPokedRenderer(
63         rwi->GetEventPosition( )[ 0 ],
64         rwi->GetEventPosition( )[ 1 ]
65         );
66       this->Pan( );
67
68     } // fi
69
70   } // fi
71
72   // Get mouse pointer position
73   static int idx[ 2 ];
74   static double pos[ 3 ];
75   if( !( this->_PickPosition( idx, pos ) ) )
76     return;
77
78   // Invoke possible specialized events
79   auto i = this->m_MouseMoveCommands.begin( );
80   for( ; i != this->m_MouseMoveCommands.end( ); ++i )
81     i->first( i->second, button, idx, pos, alt, ctr, sft );
82 }
83
84 // -------------------------------------------------------------------------
85 void cpExtensions::Interaction::BaseInteractorStyle::
86 OnMouseWheelForward( )
87 {
88   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
89   if( rwi == NULL )
90     return;
91
92   // Invoke possible events
93   auto i = this->m_MouseWheelCommands.begin( );
94   for( ; i != this->m_MouseWheelCommands.end( ); ++i )
95     i->first(
96       i->second, 1,
97       rwi->GetAltKey( ) == 1,
98       rwi->GetControlKey( ) == 1,
99       rwi->GetShiftKey( ) == 1
100       );
101 }
102
103 // -------------------------------------------------------------------------
104 void cpExtensions::Interaction::BaseInteractorStyle::
105 OnMouseWheelBackward( )
106 {
107   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
108   if( rwi == NULL )
109     return;
110
111   // Invoke possible events
112   auto i = this->m_MouseWheelCommands.begin( );
113   for( ; i != this->m_MouseWheelCommands.end( ); ++i )
114     i->first(
115       i->second, -1,
116       rwi->GetAltKey( ) == 1,
117       rwi->GetControlKey( ) == 1,
118       rwi->GetShiftKey( ) == 1
119       );
120 }
121
122 // -------------------------------------------------------------------------
123 void cpExtensions::Interaction::BaseInteractorStyle::
124 OnLeftButtonDown( )
125 {
126   this->m_ActiveButton = Self::ButtonID_Left;
127 }
128
129 // -------------------------------------------------------------------------
130 void cpExtensions::Interaction::BaseInteractorStyle::
131 OnLeftButtonUp( )
132 {
133   this->m_ActiveButton = Self::ButtonID_None;
134 }
135
136 // -------------------------------------------------------------------------
137 void cpExtensions::Interaction::BaseInteractorStyle::
138 OnMiddleButtonDown( )
139 {
140   this->m_ActiveButton = Self::ButtonID_Middle;
141
142   // Get current position on the associated actors
143   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
144   if( rwi == NULL )
145     return;
146
147   // Get modifiers
148   bool alt = ( rwi->GetAltKey( ) == 1 );
149   bool ctr = ( rwi->GetControlKey( ) == 1 );
150   bool sft = ( rwi->GetShiftKey( ) == 1 );
151
152   if( !alt && !ctr && !sft )
153     this->StartPan( );
154 }
155
156 // -------------------------------------------------------------------------
157 void cpExtensions::Interaction::BaseInteractorStyle::
158 OnMiddleButtonUp( )
159 {
160   this->m_ActiveButton = Self::ButtonID_None;
161
162   // Get current position on the associated actors
163   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
164   if( rwi == NULL )
165     return;
166
167   // Get modifiers
168   bool alt = ( rwi->GetAltKey( ) == 1 );
169   bool ctr = ( rwi->GetControlKey( ) == 1 );
170   bool sft = ( rwi->GetShiftKey( ) == 1 );
171
172   switch( this->State )
173   {
174   case VTKIS_PAN:
175     this->EndPan( );
176     break;
177   default:
178     break;
179   } // hctiws
180 }
181
182 // -------------------------------------------------------------------------
183 void cpExtensions::Interaction::BaseInteractorStyle::
184 OnRightButtonDown( )
185 {
186   this->m_ActiveButton = Self::ButtonID_Right;
187
188   // Get current position on the associated actors
189   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
190   if( rwi == NULL )
191     return;
192
193   // Get modifiers
194   bool alt = ( rwi->GetAltKey( ) == 1 );
195   bool ctr = ( rwi->GetControlKey( ) == 1 );
196   bool sft = ( rwi->GetShiftKey( ) == 1 );
197
198   if( !alt && !ctr && !sft )
199     this->StartDolly( );
200 }
201
202 // -------------------------------------------------------------------------
203 void cpExtensions::Interaction::BaseInteractorStyle::
204 OnRightButtonUp( )
205 {
206   this->m_ActiveButton = Self::ButtonID_None;
207
208   // Get current position on the associated actors
209   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
210   if( rwi == NULL )
211     return;
212
213   // Get modifiers
214   bool alt = ( rwi->GetAltKey( ) == 1 );
215   bool ctr = ( rwi->GetControlKey( ) == 1 );
216   bool sft = ( rwi->GetShiftKey( ) == 1 );
217
218   switch( this->State )
219   {
220   case VTKIS_DOLLY:
221     this->EndDolly( );
222     break;
223   default:
224     break;
225   } // hctiws
226 }
227
228 // -------------------------------------------------------------------------
229 #define cpExtensions_BaseInteractorStyle_Click( S, T )          \
230   void cpExtensions::Interaction::BaseInteractorStyle::         \
231   On##S##T( )                                                   \
232   {                                                             \
233     vtkRenderWindowInteractor* rwi = this->GetInteractor( );    \
234     if( rwi == NULL )                                           \
235       return;                                                   \
236     static int idx[ 2 ];                                        \
237     static double pos[ 3 ];                                     \
238     if( !( this->_PickPosition( idx, pos ) ) )                  \
239       return;                                                   \
240     auto i = this->m_Mouse##T##Commands.begin( );               \
241     for( ; i != this->m_Mouse##T##Commands.end( ); ++i )        \
242       i->first(                                                 \
243         i->second,                                              \
244         Self::ButtonID_##S,                                     \
245         idx, pos,                                               \
246         rwi->GetAltKey( ) == 1,                                 \
247         rwi->GetControlKey( ) == 1,                             \
248         rwi->GetShiftKey( ) == 1                                \
249         );                                                      \
250   }
251
252 cpExtensions_BaseInteractorStyle_Click( Left, Click );
253 cpExtensions_BaseInteractorStyle_Click( Middle, Click );
254 cpExtensions_BaseInteractorStyle_Click( Right, Click );
255 cpExtensions_BaseInteractorStyle_Click( Left, DoubleClick );
256 cpExtensions_BaseInteractorStyle_Click( Middle, DoubleClick );
257 cpExtensions_BaseInteractorStyle_Click( Right, DoubleClick );
258
259 // -------------------------------------------------------------------------
260 void cpExtensions::Interaction::BaseInteractorStyle::
261 OnChar( )
262 {
263   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
264   if( rwi == NULL )
265     return;
266
267   // Invoke possible events
268   auto i = this->m_KeyCommands.begin( );
269   for( ; i != this->m_KeyCommands.end( ); ++i )
270     i->first( i->second, rwi->GetKeyCode( ) );
271 }
272
273 // -------------------------------------------------------------------------
274 #define cpExtensions_BaseInteractorStyle_Global( N )            \
275   void cpExtensions::Interaction::BaseInteractorStyle::         \
276   On##N( )                                                      \
277   {                                                             \
278     vtkRenderWindowInteractor* rwi = this->GetInteractor( );    \
279     if( rwi == NULL )                                           \
280       return;                                                   \
281     auto i = this->m_##N##Commands.begin( );                    \
282     for( ; i != this->m_##N##Commands.end( ); ++i )             \
283       i->first( i->second );                                    \
284   }
285
286 cpExtensions_BaseInteractorStyle_Global( Expose );
287 cpExtensions_BaseInteractorStyle_Global( Configure );
288 cpExtensions_BaseInteractorStyle_Global( Enter );
289 cpExtensions_BaseInteractorStyle_Global( Leave );
290
291 // -------------------------------------------------------------------------
292 void cpExtensions::Interaction::BaseInteractorStyle::
293 Dolly( )
294 {
295   if( this->CurrentRenderer == NULL )
296     return;
297
298   vtkRenderWindowInteractor* rwi = this->GetInteractor( );
299   double *center = this->CurrentRenderer->GetCenter( );
300   int dy = rwi->GetEventPosition( )[ 1 ] - rwi->GetLastEventPosition( )[ 1 ];
301   double dyf = this->m_MotionFactor * dy / center[ 1 ];
302   this->_Dolly( std::pow( 1.1, dyf ) );
303 }
304
305 // -------------------------------------------------------------------------
306 void cpExtensions::Interaction::BaseInteractorStyle::
307 Pan( )
308 {
309   if( this->CurrentRenderer == NULL )
310     return;
311
312   vtkRenderWindowInteractor* rwi = this->Interactor;
313   double viewFocus[ 4 ], focalDepth, viewPoint[ 3 ];
314   double newPickPoint[ 4 ], oldPickPoint[ 4 ], motionVector[ 3 ];
315
316   // Calculate the focal depth since we'll be using it a lot
317   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( );
318   camera->GetFocalPoint( viewFocus );
319   this->ComputeWorldToDisplay(
320     viewFocus[ 0 ], viewFocus[ 1 ], viewFocus[ 2 ], viewFocus
321     );
322   focalDepth = viewFocus[ 2 ];
323   this->ComputeDisplayToWorld(
324     rwi->GetEventPosition( )[ 0 ],
325     rwi->GetEventPosition( )[ 1 ],
326     focalDepth,
327     newPickPoint
328     );
329
330   // Has to recalc old mouse point since the viewport has moved,
331   // so can't move it outside the loop
332   this->ComputeDisplayToWorld(
333     rwi->GetLastEventPosition( )[ 0 ],
334     rwi->GetLastEventPosition( )[ 1 ],
335     focalDepth,
336     oldPickPoint
337     );
338
339   // Camera motion is reversed
340   motionVector[ 0 ] = oldPickPoint[ 0 ] - newPickPoint[ 0 ];
341   motionVector[ 1 ] = oldPickPoint[ 1 ] - newPickPoint[ 1 ];
342   motionVector[ 2 ] = oldPickPoint[ 2 ] - newPickPoint[ 2 ];
343
344   camera->GetFocalPoint( viewFocus );
345   camera->GetPosition( viewPoint );
346   camera->SetFocalPoint(
347     motionVector[ 0 ] + viewFocus[ 0 ],
348     motionVector[ 1 ] + viewFocus[ 1 ],
349     motionVector[ 2 ] + viewFocus[ 2 ]
350     );
351   camera->SetPosition(
352     motionVector[ 0 ] + viewPoint[ 0 ],
353     motionVector[ 1 ] + viewPoint[ 1 ],
354     motionVector[ 2 ] + viewPoint[ 2 ]
355     );
356   if( rwi->GetLightFollowCamera( ) )
357     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( );
358   rwi->Render( );
359 }
360
361 // -------------------------------------------------------------------------
362 cpExtensions::Interaction::BaseInteractorStyle::
363 BaseInteractorStyle( )
364   : Superclass( ),
365     m_MotionFactor( double( 10 ) )
366 {
367   this->m_LeftButtonEvent.Reset( );
368   this->m_MiddleButtonEvent.Reset( );
369   this->m_RightButtonEvent.Reset( );
370   this->m_ActiveButton = Self::ButtonID_None;
371
372   this->EventCallbackCommand->SetCallback( Self::_ProcessEvents );
373 }
374
375 // -------------------------------------------------------------------------
376 cpExtensions::Interaction::BaseInteractorStyle::
377 ~BaseInteractorStyle( )
378 {
379 }
380
381 // -------------------------------------------------------------------------
382 void cpExtensions::Interaction::BaseInteractorStyle::
383 _Dolly( double factor )
384 {
385   if( this->CurrentRenderer == NULL )
386     return;
387
388   vtkCamera* camera = this->CurrentRenderer->GetActiveCamera( );
389   if( camera->GetParallelProjection( ) == 0 )
390   {
391     camera->Dolly( factor );
392     if( this->AutoAdjustCameraClippingRange )
393       this->CurrentRenderer->ResetCameraClippingRange( );
394   }
395   else
396     camera->SetParallelScale( camera->GetParallelScale( ) / factor );
397   if( this->Interactor->GetLightFollowCamera( ) )
398     this->CurrentRenderer->UpdateLightsGeometryToFollowCamera( );
399   this->Interactor->Render( );
400 }
401
402 // -------------------------------------------------------------------------
403 void cpExtensions::Interaction::BaseInteractorStyle::
404 _ProcessEvents(
405   vtkObject* object,
406   unsigned long event,
407   void* clientdata,
408   void* calldata
409   )
410 {
411   // Get active style and interactor
412   Self* s = reinterpret_cast< Self* >( clientdata );
413   if( s == NULL )
414     return;
415
416   // Process events
417   switch( event )
418   {
419   case vtkCommand::MouseMoveEvent:
420   {
421     s->OnMouseMove( );
422   }
423   break;
424   case vtkCommand::LeftButtonPressEvent:
425   {
426     unsigned char nc = s->m_LeftButtonEvent.Clicks( );
427     if( nc == 2 )
428       s->OnLeftDoubleClick( );
429     else if( nc == 1 )
430       s->OnLeftClick( );
431     s->OnLeftButtonDown( );
432   }
433   break;
434   case vtkCommand::LeftButtonReleaseEvent:
435   {
436     s->m_LeftButtonEvent.Release( );
437     s->OnLeftButtonUp( );
438   }
439   break;
440   case vtkCommand::MiddleButtonPressEvent:
441   {
442     unsigned char nc = s->m_MiddleButtonEvent.Clicks( );
443     if( nc == 2 )
444       s->OnMiddleDoubleClick( );
445     else if( nc == 1 )
446       s->OnMiddleClick( );
447     s->OnMiddleButtonDown( );
448   }
449   break;
450   case vtkCommand::MiddleButtonReleaseEvent:
451   {
452     s->m_MiddleButtonEvent.Release( );
453     s->OnMiddleButtonUp( );
454   }
455   break;
456   case vtkCommand::RightButtonPressEvent:
457   {
458     unsigned char nc = s->m_RightButtonEvent.Clicks( );
459     if( nc == 2 )
460       s->OnRightDoubleClick( );
461     else if( nc == 1 )
462       s->OnRightClick( );
463     s->OnRightButtonDown( );
464   }
465   break;
466   case vtkCommand::RightButtonReleaseEvent:
467   {
468     s->m_RightButtonEvent.Release( );
469     s->OnRightButtonUp( );
470   }
471   break;
472   case vtkCommand::MouseWheelForwardEvent:
473   {
474     s->OnMouseWheelForward( );
475   }
476   break;
477   case vtkCommand::MouseWheelBackwardEvent:
478   {
479     s->OnMouseWheelBackward( );
480   }
481   break;
482   case vtkCommand::KeyPressEvent:
483   {
484     s->OnKeyDown( );
485     s->OnKeyPress( );
486   }
487   break;
488   case vtkCommand::KeyReleaseEvent:
489   {
490     s->OnKeyUp( );
491     s->OnKeyRelease( );
492   }
493   break;
494   case vtkCommand::CharEvent:
495   {
496     s->OnChar( );
497   }
498   break;
499   case vtkCommand::ExposeEvent:
500   {
501     s->OnExpose( );
502   }
503   break;
504   case vtkCommand::ConfigureEvent:
505   {
506     s->OnConfigure( );
507   }
508   break;
509   case vtkCommand::EnterEvent:
510   {
511     s->OnEnter( );
512   }
513   break;
514   case vtkCommand::LeaveEvent:
515   {
516     s->OnLeave( );
517   }
518   break;
519   case vtkCommand::TimerEvent:
520   {
521     // Do nothing
522   }
523   break;
524   case vtkCommand::DeleteEvent:
525   {
526     s->SetInteractor( 0 );
527   }
528   break;
529   case vtkCommand::TDxMotionEvent:
530   case vtkCommand::TDxButtonPressEvent:
531   case vtkCommand::TDxButtonReleaseEvent:
532   {
533     s->DelegateTDxEvent( event, calldata );
534   }
535   break;
536   default:
537     break;
538   } // hctiws
539 }
540
541 // eof - $RCSfile$