0025338: MFC standard samples: 3D selection rectangle blinking
[occt.git] / samples / mfc / standard / Common / OCC_3dView.cpp
1 // OCC_3dView.cpp: implementation of the OCC_3dView class.
2 //
3
4 #include "stdafx.h"
5
6 #include "OCC_3dView.h"
7 #include "OCC_App.h"
8 #include "OCC_3dBaseDoc.h"
9 #include <res\OCC_Resource.h>
10
11 #include <Graphic3d_ExportFormat.hxx>
12 #include <Graphic3d_Camera.hxx>
13
14 #include <OpenGl_GraphicDriver.hxx>
15
16 #define ValZWMin 1
17
18 IMPLEMENT_DYNCREATE(OCC_3dView, CView)
19
20 BEGIN_MESSAGE_MAP(OCC_3dView, CView)
21         //{{AFX_MSG_MAP(OCC_3dView)
22         ON_COMMAND(ID_BUTTONAxo, OnBUTTONAxo)
23         ON_COMMAND(ID_BUTTONBack, OnBUTTONBack)
24         ON_COMMAND(ID_BUTTONBottom, OnBUTTONBottom)
25         ON_COMMAND(ID_BUTTONFront, OnBUTTONFront)
26         ON_COMMAND(ID_BUTTONHlrOff, OnBUTTONHlrOff)
27         ON_COMMAND(ID_BUTTONHlrOn, OnBUTTONHlrOn)
28         ON_COMMAND(ID_BUTTONLeft, OnBUTTONLeft)
29         ON_COMMAND(ID_BUTTONPan, OnBUTTONPan)
30         ON_COMMAND(ID_BUTTONPanGlo, OnBUTTONPanGlo)
31         ON_COMMAND(ID_BUTTONReset, OnBUTTONReset)
32         ON_COMMAND(ID_BUTTONRight, OnBUTTONRight)
33         ON_COMMAND(ID_BUTTONRot, OnBUTTONRot)
34         ON_COMMAND(ID_BUTTONTop, OnBUTTONTop)
35         ON_COMMAND(ID_BUTTONZoomAll, OnBUTTONZoomAll)
36   ON_COMMAND(ID_BUTTON_STEREOCONFIG, OnStereoConfigButton)
37         ON_WM_SIZE()
38     ON_COMMAND(ID_FILE_EXPORT_IMAGE, OnFileExportImage)
39         ON_COMMAND(ID_BUTTONZoomProg, OnBUTTONZoomProg)
40         ON_COMMAND(ID_BUTTONZoomWin, OnBUTTONZoomWin)
41         ON_WM_LBUTTONDOWN()
42         ON_WM_LBUTTONUP()
43         ON_WM_MBUTTONDOWN()
44         ON_WM_MBUTTONUP()
45         ON_WM_MOUSEMOVE()
46         ON_WM_RBUTTONDOWN()
47         ON_WM_RBUTTONUP()
48         ON_UPDATE_COMMAND_UI(ID_BUTTONHlrOff, OnUpdateBUTTONHlrOff)
49         ON_UPDATE_COMMAND_UI(ID_BUTTONHlrOn, OnUpdateBUTTONHlrOn)
50         ON_UPDATE_COMMAND_UI(ID_BUTTONPanGlo, OnUpdateBUTTONPanGlo)
51         ON_UPDATE_COMMAND_UI(ID_BUTTONPan, OnUpdateBUTTONPan)
52         ON_UPDATE_COMMAND_UI(ID_BUTTONZoomProg, OnUpdateBUTTONZoomProg)
53         ON_UPDATE_COMMAND_UI(ID_BUTTONZoomWin, OnUpdateBUTTONZoomWin)
54         ON_UPDATE_COMMAND_UI(ID_BUTTONRot, OnUpdateBUTTONRot)
55   ON_UPDATE_COMMAND_UI(ID_BUTTON_STEREOCONFIG, OnUpdateStereoConfigButton)
56         ON_COMMAND(ID_Modify_ChangeBackground     , OnModifyChangeBackground)
57         //}}AFX_MSG_MAP
58 END_MESSAGE_MAP()
59
60 /////////////////////////////////////////////////////////////////////////////
61 // OCC_3dView construction/destruction
62
63 OCC_3dView::OCC_3dView()
64 : myCurrentMode (CurAction3d_Nothing),
65   myWidth  (0),
66   myHeight (0),
67   myHlrModeIsOn (Standard_False)
68 {
69   // TODO: add construction code here
70 }
71
72 OCC_3dView::~OCC_3dView()
73 {
74         if (myView.IsNull())
75   {
76     myView->Remove();
77   }
78
79   delete m_pStereoDlg;
80 }
81
82 BOOL OCC_3dView::PreCreateWindow(CREATESTRUCT& cs)
83 {
84         // TODO: Modify the Window class or styles here by modifying
85         //  the CREATESTRUCT cs
86         return CView::PreCreateWindow(cs);
87 }
88
89 /////////////////////////////////////////////////////////////////////////////
90 // OCC_3dView drawing
91 void OCC_3dView::OnInitialUpdate() 
92 {
93   CView::OnInitialUpdate();
94
95   myView = GetDocument()->GetViewer()->CreateView();
96
97   // store for restore state after rotation (which is in Degenerated mode)
98   myHlrModeIsOn = Standard_False;
99   myView->SetComputedMode (myHlrModeIsOn);
100
101   Handle(OpenGl_GraphicDriver) aDriver = 
102     Handle(OpenGl_GraphicDriver)::DownCast (((OCC_App*)AfxGetApp())->GetGraphicDriver());
103
104   Handle(WNT_Window) aWNTWindow = new WNT_Window(GetSafeHwnd());
105
106   myView->SetWindow(aWNTWindow);
107   myView->Camera()->SetProjectionType (aDriver->Options().contextStereo
108     ? Graphic3d_Camera::Projection_Stereo
109     : Graphic3d_Camera::Projection_Orthographic);
110
111   if (!aWNTWindow->IsMapped())
112   {
113     aWNTWindow->Map();
114   }
115
116   // store the mode ( nothing , dynamic zooming, dynamic ... )
117   myCurrentMode = CurAction3d_Nothing;
118
119   m_pStereoDlg = new OCC_StereoConfigDlg (this);
120   m_pStereoDlg->SetView (myView);
121   m_pStereoDlg->Create (IDD_DIALOG_STEREO, this);
122 }
123
124 void OCC_3dView::OnDraw(CDC* /*pDC*/)
125 {
126   CRect aRect;
127   GetWindowRect(aRect);
128   if(myWidth != aRect.Width() || myHeight != aRect.Height()) {
129     myWidth = aRect.Width();
130     myHeight = aRect.Height();
131     ::PostMessage ( GetSafeHwnd() , WM_SIZE , SW_SHOW , myWidth + myHeight*65536 );
132   }
133   myView->Redraw();
134 }
135
136 /////////////////////////////////////////////////////////////////////////////
137 // OCC_3dView diagnostics
138
139 #ifdef _DEBUG
140 void OCC_3dView::AssertValid() const
141 {
142         CView::AssertValid();
143 }
144
145 void OCC_3dView::Dump(CDumpContext& dc) const
146 {
147         CView::Dump(dc);
148 }
149
150 OCC_3dDoc* OCC_3dView::GetDocument() // non-debug version is inline
151 {
152 //      ASSERT(m_pDocument->IsKindOf(RUNTIME_CLASS(OCC_3dBaseDoc)));
153         return (OCC_3dDoc*)m_pDocument;
154 }
155
156 #endif //_DEBUG
157
158 /////////////////////////////////////////////////////////////////////////////
159 // OCC_3dView message handlers
160 void OCC_3dView::OnFileExportImage()
161 {
162   GetDocument()->ExportView (myView);
163 }
164
165 void OCC_3dView::OnSize(UINT /*nType*/, int /*cx*/, int /*cy*/) 
166 {
167   if (!myView.IsNull())
168    myView->MustBeResized();
169 }
170
171 // See the back View
172 void OCC_3dView::OnBUTTONBack() 
173 {
174   myView->SetProj(V3d_Xneg);
175
176
177 // See the front View
178 void OCC_3dView::OnBUTTONFront() 
179 {
180   myView->SetProj(V3d_Xpos);
181
182
183 // See the bottom View
184 void OCC_3dView::OnBUTTONBottom() 
185 {
186   myView->SetProj(V3d_Zneg);
187 }
188
189 // See the top View
190 void OCC_3dView::OnBUTTONTop() 
191 {
192   myView->SetProj(V3d_Zpos);
193 }       
194
195 // See the left View
196 void OCC_3dView::OnBUTTONLeft() 
197 {
198   myView->SetProj(V3d_Ypos);
199 }
200
201 // See the right View
202 void OCC_3dView::OnBUTTONRight() 
203 {
204   myView->SetProj(V3d_Yneg);
205
206
207 // See the axonometric View
208 void OCC_3dView::OnBUTTONAxo() 
209 {
210   myView->SetProj(V3d_XposYnegZpos);
211
212
213 void OCC_3dView::OnBUTTONHlrOff() 
214 {
215   myHlrModeIsOn = Standard_False;
216   myView->SetComputedMode (myHlrModeIsOn);
217 }
218
219 void OCC_3dView::OnBUTTONHlrOn() 
220 {
221   SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
222   myHlrModeIsOn = Standard_True;
223   myView->SetComputedMode (myHlrModeIsOn);
224   SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
225 }
226
227 void OCC_3dView::OnBUTTONPan() 
228 {
229   myCurrentMode = CurAction3d_DynamicPanning;
230 }
231
232 void OCC_3dView::OnBUTTONPanGlo() 
233 {
234   // save the current zoom value 
235   myCurZoom = myView->Scale();
236   // Do a Global Zoom 
237   //myView->FitAll();
238   // Set the mode 
239   myCurrentMode = CurAction3d_GlobalPanning;
240 }
241
242 void OCC_3dView::OnBUTTONReset() 
243 {
244   myView->Reset();
245 }
246
247 void OCC_3dView::OnBUTTONRot() 
248 {
249   myCurrentMode = CurAction3d_DynamicRotation; 
250 }
251
252 void OCC_3dView::OnBUTTONZoomAll() 
253 {
254   myView->FitAll();
255   myView->ZFitAll();
256 }
257
258 void OCC_3dView::OnBUTTONZoomProg() 
259 {  myCurrentMode = CurAction3d_DynamicZooming; }
260
261 void OCC_3dView::OnBUTTONZoomWin() 
262 {  myCurrentMode = CurAction3d_WindowZooming; }
263
264 void OCC_3dView::OnLButtonDown(UINT nFlags, CPoint point) 
265 {
266   //  save the current mouse coordinate in min 
267   myXmin=point.x;  myYmin=point.y;
268   myXmax=point.x;  myYmax=point.y;
269
270   if ( nFlags & MK_CONTROL ) 
271   {
272     // Button MB1 down Control :start zomming 
273     // SetCursor(AfxGetApp()->LoadStandardCursor());
274   }
275   else // if ( Ctrl )
276   {
277     switch (myCurrentMode)
278     {
279     case CurAction3d_Nothing : // start a drag
280       if (nFlags & MK_SHIFT)
281         GetDocument()->ShiftDragEvent(myXmax,myYmax,-1,myView);
282       else
283         GetDocument()->DragEvent(myXmax,myYmax,-1,myView);
284       break;
285       break;
286     case CurAction3d_DynamicZooming : // noting
287       break;
288     case CurAction3d_WindowZooming : // noting
289       break;
290     case CurAction3d_DynamicPanning :// noting
291       break;
292     case CurAction3d_GlobalPanning :// noting
293       break;
294     case  CurAction3d_DynamicRotation :
295       if (myHlrModeIsOn)
296       {
297         myView->SetComputedMode (Standard_False);
298       }
299
300       myView->StartRotation(point.x,point.y);  
301       break;
302     default :
303       Standard_Failure::Raise(" incompatible Current Mode ");
304       break;
305     }
306   }
307 }
308
309 void OCC_3dView::OnLButtonUp(UINT nFlags, CPoint point) 
310 {
311   if ( nFlags & MK_CONTROL ) 
312   {
313     return;
314   }
315   else // if ( Ctrl )
316   {
317     const Handle(AIS_InteractiveContext)& aContext = GetDocument()->GetAISContext();
318     switch (myCurrentMode)
319     {
320     case CurAction3d_Nothing :
321       if (point.x == myXmin && point.y == myYmin)
322       { // no offset between down and up --> selectEvent
323         myXmax=point.x;  
324         myYmax=point.y;
325         if (nFlags & MK_SHIFT )
326           GetDocument()->ShiftInputEvent(point.x,point.y,myView);
327         else
328           GetDocument()->InputEvent     (point.x,point.y,myView);
329       } else
330       {
331         myXmax=point.x;    myYmax=point.y;
332         drawRectangle (myXmin, myYmin, myXmax, myYmax, aContext, Standard_False);
333         if (nFlags & MK_SHIFT)
334           GetDocument()->ShiftDragEvent(point.x,point.y,1,myView);
335         else
336           GetDocument()->DragEvent(point.x,point.y,1,myView);
337       }
338       break;
339     case CurAction3d_DynamicZooming :
340       myCurrentMode = CurAction3d_Nothing;
341       break;
342     case CurAction3d_WindowZooming :
343       myXmax=point.x;        myYmax=point.y;
344       drawRectangle (myXmin, myYmin, myXmax, myYmax, aContext, Standard_False);
345       if ((abs(myXmin-myXmax)>ValZWMin) || (abs(myYmin-myYmax)>ValZWMin))
346         // Test if the zoom window is greater than a minimale window.
347       {
348         // Do the zoom window between Pmin and Pmax
349         myView->WindowFitAll(myXmin,myYmin,myXmax,myYmax);  
350       }  
351       myCurrentMode = CurAction3d_Nothing;
352       break;
353     case CurAction3d_DynamicPanning :
354       myCurrentMode = CurAction3d_Nothing;
355       break;
356     case CurAction3d_GlobalPanning :
357       myView->Place(point.x,point.y,myCurZoom); 
358       myCurrentMode = CurAction3d_Nothing;
359       break;
360     case  CurAction3d_DynamicRotation :
361       myCurrentMode = CurAction3d_Nothing;
362       if (myHlrModeIsOn)
363       {
364         CWaitCursor aWaitCursor;
365         myView->SetComputedMode (myHlrModeIsOn);
366       }
367       else
368       {
369         myView->SetComputedMode (myHlrModeIsOn);
370       }
371       break;
372     default :
373       Standard_Failure::Raise(" incompatible Current Mode ");
374       break;
375     } //switch (myCurrentMode)
376   } //  else // if ( Ctrl )
377 }
378
379 void OCC_3dView::OnMButtonDown(UINT nFlags, CPoint /*point*/) 
380 {
381   if ( nFlags & MK_CONTROL ) 
382   {
383     // Button MB2 down Control : panning init  
384     // SetCursor(AfxGetApp()->LoadStandardCursor());   
385   }
386 }
387
388 void OCC_3dView::OnMButtonUp(UINT nFlags, CPoint /*point*/) 
389 {
390   if ( nFlags & MK_CONTROL ) 
391   {
392     // Button MB2 down Control : panning init  
393     // SetCursor(AfxGetApp()->LoadStandardCursor());   
394   }
395 }
396
397 void OCC_3dView::OnRButtonDown(UINT nFlags, CPoint point) 
398 {
399   if ( nFlags & MK_CONTROL )
400   {
401     if (myHlrModeIsOn)
402     {
403       myView->SetComputedMode (Standard_False);
404     }
405     myView->StartRotation(point.x,point.y);  
406   }
407   else // if ( Ctrl )
408   {
409     GetDocument()->Popup(point.x,point.y,myView);
410   }     
411 }
412
413 void OCC_3dView::OnRButtonUp(UINT /*nFlags*/, CPoint /*point*/) 
414 {
415     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_WAIT));
416     myView->SetComputedMode (myHlrModeIsOn);
417     SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW));
418 }
419
420 void OCC_3dView::OnMouseMove(UINT nFlags, CPoint point) 
421 {
422    //   ============================  LEFT BUTTON =======================
423   if ( nFlags & MK_LBUTTON)
424   {
425     if ( nFlags & MK_CONTROL ) 
426     {
427       // move with MB1 and Control : on the dynamic zooming  
428       // Do the zoom in function of mouse's coordinates  
429       myView->Zoom (myXmax,myYmax,point.x,point.y); 
430       // save the current mouse coordinate in min 
431       myXmax = point.x; 
432       myYmax = point.y; 
433     }
434     else // if ( Ctrl )
435     {
436       const Handle(AIS_InteractiveContext)& aContext = GetDocument()->GetAISContext();
437       switch (myCurrentMode)
438       {
439       case CurAction3d_Nothing :
440         myXmax = point.x;
441         myYmax = point.y;
442
443         if (nFlags & MK_SHIFT)
444           GetDocument()->ShiftDragEvent(myXmax,myYmax,0,myView);
445         else
446           GetDocument()->DragEvent(myXmax,myYmax,0,myView);
447
448         drawRectangle (myXmin, myYmin, myXmax, myYmax, aContext);
449
450         break;
451       case CurAction3d_DynamicZooming :
452         myView->Zoom(myXmax,myYmax,point.x,point.y); 
453         // save the current mouse coordinate in min \n";
454         myXmax = point.x;
455         myYmax = point.y;
456         break;
457       case CurAction3d_WindowZooming :
458         myXmax = point.x;
459         myYmax = point.y;
460         drawRectangle (myXmin, myYmin, myXmax, myYmax, aContext);
461         break;
462       case CurAction3d_DynamicPanning :
463         myView->Pan(point.x-myXmax,myYmax-point.y); // Realize the panning
464         myXmax = point.x; myYmax = point.y;     
465         break;
466       case CurAction3d_GlobalPanning : // nothing           
467         break;
468       case  CurAction3d_DynamicRotation :
469         myView->Rotation(point.x,point.y);
470         myView->Redraw();
471         break;
472       default :
473         Standard_Failure::Raise(" incompatible Current Mode ");
474         break;
475       }//  switch (myCurrentMode)
476     }// if ( nFlags & MK_CONTROL )  else 
477   } 
478   else if ( nFlags & MK_MBUTTON)
479   {
480     if ( nFlags & MK_CONTROL ) 
481     {
482       myView->Pan(point.x-myXmax,myYmax-point.y); // Realize the panning
483       myXmax = point.x;
484       myYmax = point.y;
485     }
486   } 
487   else if ( nFlags & MK_RBUTTON)
488   {
489     if ( nFlags & MK_CONTROL ) 
490     {
491       myView->Rotation(point.x,point.y);
492     }
493   }
494   else 
495   {  // No buttons
496     myXmax = point.x;
497     myYmax = point.y;
498     if (nFlags & MK_SHIFT)
499       GetDocument()->ShiftMoveEvent(point.x,point.y,myView);
500     else
501       GetDocument()->MoveEvent(point.x,point.y,myView);
502   }
503 }
504
505 void OCC_3dView::OnUpdateBUTTONHlrOff(CCmdUI* pCmdUI) 
506 {
507   pCmdUI->SetCheck (!myHlrModeIsOn);
508   pCmdUI->Enable   (myHlrModeIsOn);
509 }
510
511 void OCC_3dView::OnUpdateBUTTONHlrOn(CCmdUI* pCmdUI)
512 {
513   pCmdUI->SetCheck (myHlrModeIsOn);
514   pCmdUI->Enable   (!myHlrModeIsOn);
515 }
516
517 void OCC_3dView::OnUpdateBUTTONPanGlo(CCmdUI* pCmdUI) 
518 {
519     pCmdUI->SetCheck (myCurrentMode == CurAction3d_GlobalPanning);
520         pCmdUI->Enable   (myCurrentMode != CurAction3d_GlobalPanning);  
521         
522 }
523
524 void OCC_3dView::OnUpdateBUTTONPan(CCmdUI* pCmdUI) 
525 {
526     pCmdUI->SetCheck (myCurrentMode == CurAction3d_DynamicPanning);
527         pCmdUI->Enable   (myCurrentMode != CurAction3d_DynamicPanning );        
528 }
529
530 void OCC_3dView::OnUpdateBUTTONZoomProg(CCmdUI* pCmdUI) 
531 {
532     pCmdUI->SetCheck (myCurrentMode == CurAction3d_DynamicZooming );
533         pCmdUI->Enable   (myCurrentMode != CurAction3d_DynamicZooming); 
534 }
535
536 void OCC_3dView::OnUpdateBUTTONZoomWin(CCmdUI* pCmdUI) 
537 {
538     pCmdUI->SetCheck (myCurrentMode == CurAction3d_WindowZooming);
539         pCmdUI->Enable   (myCurrentMode != CurAction3d_WindowZooming);  
540 }
541
542 void OCC_3dView::OnUpdateBUTTONRot(CCmdUI* pCmdUI) 
543 {
544     pCmdUI->SetCheck (myCurrentMode == CurAction3d_DynamicRotation);
545         pCmdUI->Enable   (myCurrentMode != CurAction3d_DynamicRotation);        
546 }
547
548 void OCC_3dView::OnModifyChangeBackground() 
549 {
550         Standard_Real R1;
551         Standard_Real G1;
552         Standard_Real B1;
553     myView->BackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
554         COLORREF m_clr ;
555         m_clr = RGB(R1*255,G1*255,B1*255);
556
557         CColorDialog dlgColor(m_clr);
558         if (dlgColor.DoModal() == IDOK)
559         {
560                 m_clr = dlgColor.GetColor();
561                 R1 = GetRValue(m_clr)/255.;
562                 G1 = GetGValue(m_clr)/255.;
563                 B1 = GetBValue(m_clr)/255.;
564         myView->SetBackgroundColor(Quantity_TOC_RGB,R1,G1,B1);
565         }
566     myView->Redraw();
567 }
568
569 //=============================================================================
570 // function: OnStereoConfigButton
571 // purpose: Open stereographic configuration dialog
572 //=============================================================================
573 void OCC_3dView::OnStereoConfigButton()
574 {
575   m_pStereoDlg->ShowWindow (SW_SHOW);
576 }
577
578 //=============================================================================
579 // function: OnUpdateStereoConfigButton
580 // purpose: Enable / disable state of stereo configuration button
581 //=============================================================================
582 void OCC_3dView::OnUpdateStereoConfigButton (CCmdUI* theCmdUI)
583 {
584   // get camera
585   Handle(Graphic3d_Camera) aCamera = myView->Camera();
586
587   // check that button is enabled
588   Standard_Boolean isEnabled = !aCamera.IsNull() && aCamera->IsStereo();
589
590   // update toggle state
591   theCmdUI->Enable (isEnabled);
592
593   if (!isEnabled)
594   {
595     m_pStereoDlg->ShowWindow (SW_HIDE);
596   }
597 }