0031622: Samples - update MFC Animation sample with proper frame updates
[occt.git] / samples / mfc / standard / 09_Animation / src / AnimationView3D.cpp
1 // AnimationView3D.cpp : implementation of the CAnimationView3D class
2 //
3
4 #include "stdafx.h"
5
6 #include "AnimationView3D.h"
7
8 #include "AnimationApp.h"
9 #include "ShadingDialog.h"
10 #include "AnimationDoc.h"
11
12 #include <AIS_RubberBand.hxx>
13
14 #ifdef _DEBUG
15 //#define new DEBUG_NEW by CasCade
16 #undef THIS_FILE
17 static char THIS_FILE[] = __FILE__;
18 #endif
19 static int rotCount = 0;
20
21 // for elastic bean selection
22 #define ValZWMin 1
23
24
25 /////////////////////////////////////////////////////////////////////////////
26 // CAnimationView3D
27
28 IMPLEMENT_DYNCREATE(CAnimationView3D, CView)
29
30 BEGIN_MESSAGE_MAP(CAnimationView3D, CView)
31         //{{AFX_MSG_MAP(CAnimationView3D)
32         ON_COMMAND(ID_BUTTONAxo, OnBUTTONAxo)
33         ON_COMMAND(ID_BUTTONBack, OnBUTTONBack)
34         ON_COMMAND(ID_BUTTONBottom, OnBUTTONBottom)
35         ON_COMMAND(ID_BUTTONFront, OnBUTTONFront)
36         ON_COMMAND(ID_BUTTONHlrOff, OnBUTTONHlrOff)
37         ON_COMMAND(ID_BUTTONHlrOn, OnBUTTONHlrOn)
38         ON_COMMAND(ID_BUTTONLeft, OnBUTTONLeft)
39         ON_COMMAND(ID_BUTTONPan, OnBUTTONPan)
40         ON_COMMAND(ID_BUTTONPanGlo, OnBUTTONPanGlo)
41         ON_COMMAND(ID_BUTTONReset, OnBUTTONReset)
42         ON_COMMAND(ID_BUTTONRight, OnBUTTONRight)
43         ON_COMMAND(ID_BUTTONRot, OnBUTTONRot)
44         ON_COMMAND(ID_BUTTONTop, OnBUTTONTop)
45         ON_COMMAND(ID_BUTTONZoomAll, OnBUTTONZoomAll)
46     ON_COMMAND(ID_FILE_EXPORT_IMAGE, OnFileExportImage)
47         ON_WM_SIZE()
48         ON_COMMAND(ID_BUTTONZoomProg, OnBUTTONZoomProg)
49         ON_COMMAND(ID_BUTTONZoomWin, OnBUTTONZoomWin)
50         ON_WM_MOUSEWHEEL()
51         ON_WM_LBUTTONDOWN()
52         ON_WM_LBUTTONUP()
53         ON_WM_MBUTTONDOWN()
54         ON_WM_MBUTTONUP()
55         ON_WM_MOUSEMOVE()
56         ON_WM_RBUTTONDOWN()
57         ON_WM_RBUTTONUP()
58         ON_UPDATE_COMMAND_UI(ID_BUTTONHlrOff, OnUpdateBUTTONHlrOff)
59         ON_UPDATE_COMMAND_UI(ID_BUTTONHlrOn, OnUpdateBUTTONHlrOn)
60         ON_UPDATE_COMMAND_UI(ID_BUTTONPanGlo, OnUpdateBUTTONPanGlo)
61         ON_UPDATE_COMMAND_UI(ID_BUTTONPan, OnUpdateBUTTONPan)
62         ON_UPDATE_COMMAND_UI(ID_BUTTONZoomProg, OnUpdateBUTTONZoomProg)
63         ON_UPDATE_COMMAND_UI(ID_BUTTONZoomWin, OnUpdateBUTTONZoomWin)
64         ON_UPDATE_COMMAND_UI(ID_BUTTONRot, OnUpdateBUTTONRot)
65
66         ON_COMMAND(ID_Modify_ChangeBackground     , OnChangeBackground)
67         ON_WM_TIMER()
68         ON_COMMAND(ID_STOP, OnStop)
69         ON_COMMAND(ID_RESTART, OnRestart)
70
71         ON_COMMAND(ID_BUTTONFly, OnBUTTONFly)
72         ON_COMMAND(ID_BUTTONTurn, OnBUTTONTurn)
73         ON_UPDATE_COMMAND_UI(ID_BUTTONFly, OnUpdateBUTTONFly)
74         ON_UPDATE_COMMAND_UI(ID_BUTTONTurn, OnUpdateBUTTONTurn)
75         //}}AFX_MSG_MAP
76 // CasCade
77
78 END_MESSAGE_MAP()
79
80 /////////////////////////////////////////////////////////////////////////////
81 // CAnimationView3D construction/destruction
82
83 CAnimationView3D::CAnimationView3D()
84 : myCurZoom (0.0),
85   myHlrModeIsOn (Standard_False),
86   myIsTurnStarted (Standard_False),
87   myUpdateRequests (0),
88   myCurrentMode  (CurrentAction3d_Nothing)
89 {
90   myDefaultGestures = myMouseGestureMap;
91 }
92
93 CAnimationView3D::~CAnimationView3D()
94 {
95     myView->Remove();
96 }
97
98 BOOL CAnimationView3D::PreCreateWindow(CREATESTRUCT& cs)
99 {
100   // TODO: Modify the Window class or styles here by modifying
101   //  the CREATESTRUCT cs
102   cs.lpszClass = ::AfxRegisterWndClass(CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS | CS_OWNDC, ::LoadCursor(NULL, IDC_ARROW), NULL, NULL);
103   return CView::PreCreateWindow(cs);
104 }
105
106 /////////////////////////////////////////////////////////////////////////////
107 // CAnimationView3D drawing
108
109
110 // ================================================================
111 // Function : update3dView
112 // Purpose  :
113 // ================================================================
114 void CAnimationView3D::update3dView()
115 {
116   if (myView.IsNull())
117   {
118     return;
119   }
120
121   if (++myUpdateRequests == 1)
122   {
123     Invalidate (FALSE);
124     UpdateWindow();
125   }
126 }
127
128 // ================================================================
129 // Function : redraw3dView
130 // Purpose  :
131 // ================================================================
132 void CAnimationView3D::redraw3dView()
133 {
134   if (!myView.IsNull())
135   {
136     FlushViewEvents (GetDocument()->GetAISContext(), myView, true);
137   }
138 }
139
140 // ================================================================
141 // Function : handleViewRedraw
142 // Purpose  :
143 // ================================================================
144 void CAnimationView3D::handleViewRedraw (const Handle(AIS_InteractiveContext)& theCtx,
145                                          const Handle(V3d_View)& theView)
146 {
147   myUpdateRequests = 0;
148   if (myAnimTimer.IsStarted())
149   {
150     GetDocument()->OnMyTimer (myAnimTimer.ElapsedTime());
151     setAskNextFrame();
152   }
153   AIS_ViewController::handleViewRedraw (theCtx, theView);
154 }
155
156 void CAnimationView3D::OnDraw(CDC* /*pDC*/)
157 {
158   // always redraw immediate layer (dynamic highlighting) on Paint event,
159   // and redraw entire view content only when it is explicitly invalidated (V3d_View::Invalidate())
160   myView->InvalidateImmediate();
161   FlushViewEvents (GetDocument()->GetInteractiveContext(), myView, true);
162 }
163
164 void CAnimationView3D::OnInitialUpdate() 
165 {
166   CView::OnInitialUpdate();
167
168   // TODO: Add your specialized code here and/or call the base class
169   //    myView = GetDocument()->GetViewer()->CreateView();
170   Handle(V3d_Viewer) aViewer = GetDocument()->GetViewer();
171   aViewer->SetDefaultTypeOfView (V3d_PERSPECTIVE);
172
173   myView = aViewer->CreateView();
174   myView->SetImmediateUpdate (false);
175
176   // store for restore state after rotation (witch is in Degenerated mode)
177   myHlrModeIsOn = myView->ComputedMode();
178
179   Handle(WNT_Window) aWNTWindow = new WNT_Window (GetSafeHwnd());
180   myView->SetWindow(aWNTWindow);
181   if (!aWNTWindow->IsMapped()) aWNTWindow->Map();
182
183   // store the mode ( nothing , dynamic zooming, dynamic ... )
184   myCurrentMode = CurrentAction3d_Nothing;
185
186   CFrameWnd* pParentFrm = GetParentFrame();
187   pParentFrm->ActivateFrame(SW_SHOWMAXIMIZED);
188 }
189
190 // =======================================================================
191 // function : defineMouseGestures
192 // purpose  :
193 // =======================================================================
194 void CAnimationView3D::defineMouseGestures()
195 {
196   myMouseGestureMap.Clear();
197   switch (myCurrentMode)
198   {
199     case CurrentAction3d_Nothing:
200     {
201       myMouseGestureMap = myDefaultGestures;
202       break;
203     }
204     case CurrentAction3d_DynamicZooming:
205     {
206       myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Zoom);
207       break;
208     }
209     case CurrentAction3d_GlobalPanning:
210     {
211       break;
212     }
213     case CurrentAction3d_WindowZooming:
214     {
215       myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_ZoomWindow);
216       break;
217     }
218     case CurrentAction3d_DynamicPanning:
219     {
220       myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_Pan);
221       break;
222     }
223     case CurrentAction3d_DynamicRotation:
224     {
225       myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateOrbit);
226       break;
227     }
228     case CurrentAction3d_Fly:
229     {
230       myMouseGestureMap.Bind (Aspect_VKeyMouse_LeftButton, AIS_MouseGesture_RotateView);
231       break;
232     }
233   }
234 }
235
236 /////////////////////////////////////////////////////////////////////////////
237 // CAnimationView3D diagnostics
238
239 #ifdef _DEBUG
240 void CAnimationView3D::AssertValid() const
241 {
242         CView::AssertValid();
243 }
244
245 void CAnimationView3D::Dump(CDumpContext& dc) const
246 {
247         CView::Dump(dc);
248 }
249
250 CAnimationDoc* CAnimationView3D::GetDocument() // non-debug version is inline
251 {
252         ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(CAnimationDoc)));
253         return (CAnimationDoc*)m_pDocument;
254 }
255 #endif //_DEBUG
256
257 /////////////////////////////////////////////////////////////////////////////
258 // CAnimationView3D message handlers
259 void CAnimationView3D::OnFileExportImage()
260 {
261   GetDocument()->ExportView (myView);
262 }
263
264 void CAnimationView3D::OnSize(UINT nType, int cx, int cy)
265 {
266   CView::OnSize (nType, cx, cy);
267   if (cx != 0
268    && cy != 0
269    && !myView.IsNull())
270   {
271     myView->Window()->DoResize();
272     myView->MustBeResized();
273     myView->Invalidate();
274     update3dView();
275   }
276 }
277
278 void CAnimationView3D::OnBUTTONBack() 
279 { myView->SetProj(V3d_Ypos); } // See the back View
280 void CAnimationView3D::OnBUTTONFront() 
281 { myView->SetProj(V3d_Yneg); } // See the front View
282
283 void CAnimationView3D::OnBUTTONBottom() 
284 { myView->SetProj(V3d_Zneg); } // See the bottom View
285 void CAnimationView3D::OnBUTTONTop() 
286 { myView->SetProj(V3d_Zpos); } // See the top View      
287
288 void CAnimationView3D::OnBUTTONLeft() 
289 { myView->SetProj(V3d_Xneg); } // See the left View     
290 void CAnimationView3D::OnBUTTONRight() 
291 { myView->SetProj(V3d_Xpos); } // See the right View
292
293 void CAnimationView3D::OnBUTTONAxo() 
294 { myView->SetProj(V3d_XposYnegZpos); } // See the axonometric View
295
296 void CAnimationView3D::OnBUTTONHlrOff() 
297 {
298   myHlrModeIsOn = Standard_False;
299   myView->SetComputedMode (myHlrModeIsOn);
300   myView->Redraw();
301 }
302
303 void CAnimationView3D::OnBUTTONHlrOn() 
304 {
305   SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
306   myHlrModeIsOn = Standard_True;
307   myView->SetComputedMode (myHlrModeIsOn);
308   myView->Redraw();
309   SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
310 }
311
312 void CAnimationView3D::OnBUTTONPan() 
313 {  
314   setCurrentAction (CurrentAction3d_DynamicPanning); 
315 }
316
317 void CAnimationView3D::OnBUTTONPanGlo() 
318 {
319   // save the current zoom value 
320   myCurZoom = myView->Scale();
321   // Do a Global Zoom 
322   myView->FitAll();
323   // Set the mode 
324   setCurrentAction (CurrentAction3d_GlobalPanning);
325 }
326
327 void CAnimationView3D::OnBUTTONReset() 
328 {
329   myView->Reset(); 
330 }
331
332 void CAnimationView3D::OnBUTTONRot() 
333 {   setCurrentAction (CurrentAction3d_DynamicRotation); }
334
335
336 void CAnimationView3D::OnBUTTONZoomAll() 
337 {
338   FitAll();
339 }
340
341 void CAnimationView3D::OnBUTTONZoomProg() 
342 {  setCurrentAction (CurrentAction3d_DynamicZooming); }
343
344 void CAnimationView3D::OnBUTTONZoomWin() 
345 {  setCurrentAction (CurrentAction3d_WindowZooming); }
346
347 void CAnimationView3D::OnBUTTONFly() 
348 {  setCurrentAction (CurrentAction3d_Fly); }
349
350 void CAnimationView3D::OnBUTTONTurn() 
351 {  setCurrentAction (CurrentAction3d_Turn); }
352
353
354 void CAnimationView3D::OnLButtonDown(UINT theFlags, CPoint thePoint) 
355 {
356   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
357   PressMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_LeftButton, aFlags, false);
358   myClickPos.SetValues (thePoint.x, thePoint.y);
359   myIsTurnStarted = myCurrentMode == CurrentAction3d_Turn && aFlags == Aspect_VKeyFlags_NONE;
360   update3dView();
361 }
362
363 void CAnimationView3D::OnLButtonUp(UINT theFlags, CPoint thePoint) 
364 {
365   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
366   ReleaseMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_LeftButton, aFlags, false);
367   if (myCurrentMode == CurrentAction3d_GlobalPanning)
368   {
369     myView->Place (thePoint.x, thePoint.y, myCurZoom);
370     myView->Invalidate();
371   }
372   if (myCurrentMode != CurrentAction3d_Nothing)
373   {
374     setCurrentAction (CurrentAction3d_Nothing);
375     myIsTurnStarted = false;
376   }
377   update3dView();
378 }
379
380 void CAnimationView3D::OnMButtonDown(UINT theFlags, CPoint thePoint) 
381 {
382   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
383   PressMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_MiddleButton, aFlags, false);
384   update3dView();
385 }
386
387 void CAnimationView3D::OnMButtonUp(UINT theFlags, CPoint thePoint) 
388 {
389   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
390   ReleaseMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_MiddleButton, aFlags, false);
391   update3dView();
392   if (myCurrentMode != CurrentAction3d_Nothing)
393   {
394     setCurrentAction (CurrentAction3d_Nothing);
395   }
396 }
397
398 void CAnimationView3D::OnRButtonDown(UINT theFlags, CPoint thePoint) 
399 {
400   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
401   PressMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_RightButton, aFlags, false);
402   update3dView();
403   myClickPos.SetValues (thePoint.x, thePoint.y);
404 }
405
406 void CAnimationView3D::OnRButtonUp(UINT theFlags, CPoint thePoint) 
407 {
408   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
409   ReleaseMouseButton (Graphic3d_Vec2i (thePoint.x, thePoint.y), Aspect_VKeyMouse_RightButton, aFlags, false);
410   update3dView();
411   if (myCurrentMode != CurrentAction3d_Nothing)
412   {
413     setCurrentAction (CurrentAction3d_Nothing);
414   }
415   if (aFlags == Aspect_VKeyFlags_NONE
416    && (myClickPos - Graphic3d_Vec2i (thePoint.x, thePoint.y)).cwiseAbs().maxComp() <= 4)
417   {
418     GetDocument()->Popup (thePoint.x, thePoint.y, myView);
419   }
420 }
421
422 // =======================================================================
423 // function : OnMouseWheel
424 // purpose  :
425 // =======================================================================
426 BOOL CAnimationView3D::OnMouseWheel (UINT theFlags, short theDelta, CPoint thePoint)
427 {
428   const Standard_Real aDeltaF = Standard_Real(theDelta) / Standard_Real(WHEEL_DELTA);
429   CPoint aCursorPnt = thePoint;
430   ScreenToClient (&aCursorPnt);
431   const Graphic3d_Vec2i  aPos (aCursorPnt.x, aCursorPnt.y);
432   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
433   if (UpdateMouseScroll (Aspect_ScrollDelta (aPos, aDeltaF, aFlags)))
434   {
435     update3dView();
436   }
437   return true;
438 }
439
440 void CAnimationView3D::OnMouseMove(UINT theFlags, CPoint thePoint) 
441 {
442   TRACKMOUSEEVENT aMouseEvent;          // for WM_MOUSELEAVE
443   aMouseEvent.cbSize = sizeof(aMouseEvent);
444   aMouseEvent.dwFlags = TME_LEAVE;
445   aMouseEvent.hwndTrack = m_hWnd;
446   aMouseEvent.dwHoverTime = HOVER_DEFAULT;
447   if (!::_TrackMouseEvent (&aMouseEvent)) { TRACE("Track ERROR!\n"); }
448
449   const Graphic3d_Vec2i aNewPnt (thePoint.x, thePoint.y);
450   const Aspect_VKeyFlags aFlags = WNT_Window::MouseKeyFlagsFromEvent (theFlags);
451   if (UpdateMousePosition (aNewPnt, PressedMouseButtons(), aFlags, false))
452   {
453     update3dView();
454   }
455
456   if (myIsTurnStarted)
457   {
458     Graphic3d_Vec2i aWinSize;
459     myView->Window()->Size (aWinSize.x(), aWinSize.y());
460     const Graphic3d_Vec2i aCenter = aWinSize / 2;
461     if (myClickPos != aCenter
462      && aNewPnt != aCenter
463      && aNewPnt != myClickPos)
464     {
465       const Graphic3d_Vec2i aVecFrom = myClickPos - aCenter;
466       const Graphic3d_Vec2i aVecTo   = aNewPnt - aCenter;
467       const gp_Dir aDirFrom (aVecFrom.x() / double(aWinSize.x() / 2), aVecFrom.y() / double(aWinSize.y() / 2), 0.0);
468       const gp_Dir aDirTo   (aVecTo.x()   / double(aWinSize.x() / 2),   aVecTo.y() / double(aWinSize.y() / 2), 0.0);
469       double anAngle = aDirFrom.AngleWithRef (aDirTo, gp::DZ());
470
471       myView->SetTwist (myView->Twist() + anAngle);
472       myView->Invalidate();
473       update3dView();
474       myClickPos = aNewPnt;
475     }
476   }
477 }
478
479 void CAnimationView3D::OnUpdateBUTTONHlrOff(CCmdUI* pCmdUI) 
480 {
481   pCmdUI->SetCheck (!myHlrModeIsOn);
482   pCmdUI->Enable   (myHlrModeIsOn);
483 }
484
485 void CAnimationView3D::OnUpdateBUTTONHlrOn(CCmdUI* pCmdUI) 
486 {
487   pCmdUI->SetCheck (myHlrModeIsOn);
488   pCmdUI->Enable   (!myHlrModeIsOn);
489 }
490
491 void CAnimationView3D::OnUpdateBUTTONPanGlo(CCmdUI* pCmdUI) 
492 {
493     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_GlobalPanning);
494         pCmdUI->Enable   (myCurrentMode != CurrentAction3d_GlobalPanning);      
495         
496 }
497
498 void CAnimationView3D::OnUpdateBUTTONPan(CCmdUI* pCmdUI) 
499 {
500     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_DynamicPanning);
501         pCmdUI->Enable   (myCurrentMode != CurrentAction3d_DynamicPanning );    
502 }
503
504 void CAnimationView3D::OnUpdateBUTTONZoomProg(CCmdUI* pCmdUI) 
505 {
506     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_DynamicZooming );
507         pCmdUI->Enable   (myCurrentMode != CurrentAction3d_DynamicZooming);     
508 }
509
510 void CAnimationView3D::OnUpdateBUTTONZoomWin(CCmdUI* pCmdUI) 
511 {
512     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_WindowZooming);
513         pCmdUI->Enable   (myCurrentMode != CurrentAction3d_WindowZooming);      
514 }
515
516 void CAnimationView3D::OnUpdateBUTTONRot(CCmdUI* pCmdUI) 
517 {
518     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_DynamicRotation);
519         pCmdUI->Enable   (myCurrentMode != CurrentAction3d_DynamicRotation);    
520 }
521
522 void CAnimationView3D::OnUpdateBUTTONFly(CCmdUI* pCmdUI) 
523 {
524         pCmdUI->Enable(true);
525     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_Fly);
526 }
527
528 void CAnimationView3D::OnUpdateBUTTONTurn(CCmdUI* pCmdUI) 
529 {
530         pCmdUI->Enable(true);
531     pCmdUI->SetCheck (myCurrentMode == CurrentAction3d_Turn);
532 }
533
534 void CAnimationView3D::OnChangeBackground() 
535 {
536         Standard_Real R1;
537         Standard_Real G1;
538         Standard_Real B1;
539     myView->BackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
540         COLORREF m_clr ;
541         m_clr = RGB(R1*255,G1*255,B1*255);
542
543         CColorDialog dlgColor(m_clr);
544         if (dlgColor.DoModal() == IDOK)
545         {
546                 m_clr = dlgColor.GetColor();
547                 R1 = GetRValue(m_clr)/255.;
548                 G1 = GetGValue(m_clr)/255.;
549                 B1 = GetBValue(m_clr)/255.;
550         myView->SetBackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
551         }
552     myView->Redraw();
553 }
554
555 //==========================================================================================
556 //==========================================================================================
557 //==========================================================================================
558
559 void CAnimationView3D::OnStop() 
560 {
561   myAnimTimer.Pause();
562 }
563
564 void CAnimationView3D::OnRestart() 
565 {
566   myAnimTimer.Start();
567   update3dView();
568 }