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