VisErrorReportDialog.cpp 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992
  1. /*
  2. ** Command & Conquer Renegade(tm)
  3. ** Copyright 2025 Electronic Arts Inc.
  4. **
  5. ** This program is free software: you can redistribute it and/or modify
  6. ** it under the terms of the GNU General Public License as published by
  7. ** the Free Software Foundation, either version 3 of the License, or
  8. ** (at your option) any later version.
  9. **
  10. ** This program is distributed in the hope that it will be useful,
  11. ** but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. ** GNU General Public License for more details.
  14. **
  15. ** You should have received a copy of the GNU General Public License
  16. ** along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. */
  18. // VisErrorReportDialog.cpp : implementation file
  19. //
  20. #include "StdAfx.H"
  21. #include "LevelEdit.H"
  22. #include "VisErrorReportDialog.H"
  23. #include "Utils.H"
  24. #include "VisLog.H"
  25. #include "SceneEditor.H"
  26. #include "CameraMgr.H"
  27. #include "phys.h"
  28. #include "rendobj.h"
  29. #ifdef _DEBUG
  30. #define new DEBUG_NEW
  31. #undef THIS_FILE
  32. static char THIS_FILE[] = __FILE__;
  33. #endif
  34. /////////////////////////////////////////////////////////////////////////////
  35. //
  36. // Constants
  37. //
  38. /////////////////////////////////////////////////////////////////////////////
  39. static const int AXIS_BMP_WIDTH = 65;
  40. static const int AXIS_BMP_HEIGHT = 65;
  41. /////////////////////////////////////////////////////////////////////////////
  42. //
  43. // Local Inlines
  44. //
  45. /////////////////////////////////////////////////////////////////////////////
  46. static inline HBITMAP Load_Bitmap (UINT res_id)
  47. {
  48. return (HBITMAP)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (res_id), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
  49. }
  50. /////////////////////////////////////////////////////////////////////////////
  51. //
  52. // VisErrorReportDialogClass
  53. //
  54. /////////////////////////////////////////////////////////////////////////////
  55. VisErrorReportDialogClass::VisErrorReportDialogClass (CWnd *pParent)
  56. : m_CurrentPoint (0),
  57. m_GraphArea (0, 0, 0, 0),
  58. m_AxisArea (0, 0, 0, 0),
  59. m_CurrentMinPoint (0),
  60. m_CurrentMaxPoint (0),
  61. m_TotalPoints (0),
  62. m_bTrackingSel (false),
  63. m_TrackPixel (0),
  64. m_SelStartIndex (0),
  65. m_SelEndIndex (0),
  66. m_AxisBMP (NULL),
  67. m_AxisSelBMP (NULL),
  68. m_AxisSel (0),
  69. CDialog(VisErrorReportDialogClass::IDD, pParent)
  70. {
  71. //{{AFX_DATA_INIT(VisErrorReportDialogClass)
  72. // NOTE: the ClassWizard will add member initialization here
  73. //}}AFX_DATA_INIT
  74. m_PrevButton.normal = Load_Bitmap (IDB_LT_ARROW);
  75. m_PrevButton.disabled = Load_Bitmap (IDB_LT_ARROW_D);
  76. m_NextButton.normal = Load_Bitmap (IDB_RT_ARROW);
  77. m_NextButton.disabled = Load_Bitmap (IDB_RT_ARROW_D);
  78. m_AxisBMP = Load_Bitmap (IDB_AXIS_BMP);
  79. m_AxisSelBMP = Load_Bitmap (IDB_AXIS_SEL_BMP);
  80. m_AxisSelAreas[VIS_FORWARD].left = 1;
  81. m_AxisSelAreas[VIS_FORWARD].top = 38;
  82. m_AxisSelAreas[VIS_FORWARD].right = m_AxisSelAreas[VIS_FORWARD].left + 20;
  83. m_AxisSelAreas[VIS_FORWARD].bottom = m_AxisSelAreas[VIS_FORWARD].top + 16;
  84. m_AxisSelAreas[VIS_LEFT].left = 1;
  85. m_AxisSelAreas[VIS_LEFT].top = 12;
  86. m_AxisSelAreas[VIS_LEFT].right = m_AxisSelAreas[VIS_LEFT].left + 20;
  87. m_AxisSelAreas[VIS_LEFT].bottom = m_AxisSelAreas[VIS_LEFT].top + 16;
  88. m_AxisSelAreas[VIS_BACKWARDS].left = 42;
  89. m_AxisSelAreas[VIS_BACKWARDS].top = 13;
  90. m_AxisSelAreas[VIS_BACKWARDS].right = m_AxisSelAreas[VIS_BACKWARDS].left + 20;
  91. m_AxisSelAreas[VIS_BACKWARDS].bottom = m_AxisSelAreas[VIS_BACKWARDS].top + 16;
  92. m_AxisSelAreas[VIS_RIGHT].left = 42;
  93. m_AxisSelAreas[VIS_RIGHT].top = 39;
  94. m_AxisSelAreas[VIS_RIGHT].right = m_AxisSelAreas[VIS_RIGHT].left + 20;
  95. m_AxisSelAreas[VIS_RIGHT].bottom = m_AxisSelAreas[VIS_RIGHT].top + 16;
  96. m_AxisSelAreas[VIS_UP].left = 21;
  97. m_AxisSelAreas[VIS_UP].top = 1;
  98. m_AxisSelAreas[VIS_UP].right = m_AxisSelAreas[VIS_UP].left + 20;
  99. m_AxisSelAreas[VIS_UP].bottom = m_AxisSelAreas[VIS_UP].top + 16;
  100. m_AxisSelAreas[VIS_DOWN].left = 22;
  101. m_AxisSelAreas[VIS_DOWN].top = 47;
  102. m_AxisSelAreas[VIS_DOWN].right = m_AxisSelAreas[VIS_DOWN].left + 20;
  103. m_AxisSelAreas[VIS_DOWN].bottom = m_AxisSelAreas[VIS_DOWN].top + 16;
  104. return ;
  105. }
  106. /////////////////////////////////////////////////////////////////////////////
  107. //
  108. // ~VisErrorReportDialogClass
  109. //
  110. /////////////////////////////////////////////////////////////////////////////
  111. VisErrorReportDialogClass::~VisErrorReportDialogClass (void)
  112. {
  113. //
  114. // Free the BMPs
  115. //
  116. if (m_PrevButton.normal) ::DeleteObject (m_PrevButton.normal);
  117. if (m_PrevButton.disabled) ::DeleteObject (m_PrevButton.disabled);
  118. if (m_NextButton.normal) ::DeleteObject (m_NextButton.normal);
  119. if (m_NextButton.disabled) ::DeleteObject (m_NextButton.disabled);
  120. Free_Point_List ();
  121. return ;
  122. }
  123. /////////////////////////////////////////////////////////////////////////////
  124. //
  125. // DoDataExchange
  126. //
  127. /////////////////////////////////////////////////////////////////////////////
  128. void
  129. VisErrorReportDialogClass::DoDataExchange (CDataExchange *pDX)
  130. {
  131. CDialog::DoDataExchange(pDX);
  132. //{{AFX_DATA_MAP(VisErrorReportDialogClass)
  133. DDX_Control(pDX, IDC_ZOOM_SLIDER, m_ZoomSlider);
  134. //}}AFX_DATA_MAP
  135. return ;
  136. }
  137. BEGIN_MESSAGE_MAP(VisErrorReportDialogClass, CDialog)
  138. //{{AFX_MSG_MAP(VisErrorReportDialogClass)
  139. ON_WM_PAINT()
  140. ON_WM_VSCROLL()
  141. ON_WM_LBUTTONDOWN()
  142. ON_WM_LBUTTONUP()
  143. ON_WM_MOUSEMOVE()
  144. ON_BN_CLICKED(IDC_PREV_ERROR, OnPrevError)
  145. ON_BN_CLICKED(IDC_NEXT_ERROR, OnNextError)
  146. ON_WM_DRAWITEM()
  147. ON_WM_NCHITTEST()
  148. ON_WM_SETCURSOR()
  149. ON_WM_DESTROY()
  150. //}}AFX_MSG_MAP
  151. END_MESSAGE_MAP()
  152. /////////////////////////////////////////////////////////////////////////////
  153. //
  154. // OnInitDialog
  155. //
  156. /////////////////////////////////////////////////////////////////////////////
  157. BOOL
  158. VisErrorReportDialogClass::OnInitDialog (void)
  159. {
  160. CDialog::OnInitDialog ();
  161. //
  162. // Register this window for timer-based screen refreshing
  163. //
  164. ::SetProp (m_hWnd, "ALLOW_UPDATE", (HANDLE)1);
  165. //
  166. // Set the dimensions of the graph area
  167. //
  168. ::GetWindowRect (::GetDlgItem (m_hWnd, IDC_HISTOGRAM), &m_GraphArea);
  169. ScreenToClient (&m_GraphArea);
  170. m_GraphArea.left ++;
  171. m_GraphArea.right --;
  172. m_GraphArea.top ++;
  173. m_GraphArea.bottom --;
  174. m_Graph.Set_Dimensions (m_GraphArea.Width (), m_GraphArea.Height ());
  175. //
  176. // Set the dimensions of the 'axis' area.
  177. //
  178. CRect rect;
  179. ::GetWindowRect (::GetDlgItem (m_hWnd, IDC_AXIS_AREA), &rect);
  180. ScreenToClient (&rect);
  181. rect.left ++;
  182. rect.right --;
  183. rect.top ++;
  184. rect.bottom --;
  185. m_AxisArea.left = rect.left + (rect.Width () >> 1) - (AXIS_BMP_WIDTH >> 1);
  186. m_AxisArea.top = rect.top + (rect.Height () >> 1) - (AXIS_BMP_HEIGHT >> 1);
  187. m_AxisArea.right = m_AxisArea.left + AXIS_BMP_WIDTH;
  188. m_AxisArea.bottom = m_AxisArea.top + AXIS_BMP_HEIGHT;
  189. // Update the dialog with data from the scene
  190. Re_Sync_Data ();
  191. return TRUE;
  192. }
  193. /////////////////////////////////////////////////////////////////////////////
  194. //
  195. // Re_Sync_Data
  196. //
  197. /////////////////////////////////////////////////////////////////////////////
  198. void
  199. VisErrorReportDialogClass::Re_Sync_Data (void)
  200. {
  201. //
  202. // Get the error list from the scene
  203. //
  204. VisLogClass &vis_log = ::Get_Scene_Editor ()->Get_Vis_Log ();
  205. VIS_SAMPLE_LIST &error_list = vis_log.Peek_Error_List ();
  206. m_TotalPoints = error_list.Count ();
  207. //
  208. // Setup the 'zoom' slider
  209. //
  210. m_ZoomSlider.SetRange (2, m_TotalPoints >> 1);
  211. m_ZoomSlider.SetPos (m_TotalPoints >> 2);
  212. // Reset the range of values in the y-axis
  213. int max = (m_TotalPoints >> 1) - (m_ZoomSlider.GetPos () - 2);
  214. m_Graph.Set_Y_Axis_Range (0, max);
  215. //
  216. // Add the vis error points to the graph
  217. //
  218. Free_Point_List ();
  219. int bad_points = 0;
  220. for (int index = 0; index < error_list.Count (); index ++) {
  221. VisSampleClass *sample = error_list[index];
  222. Add_Point (*sample);
  223. //
  224. // Determining which direction resulted in the largest backface fraction
  225. //
  226. float fraction = sample->Get_Biggest_Fraction ();
  227. m_Graph.Add_Data_Point (fraction);
  228. //
  229. // Determine if this point was bad or not
  230. //
  231. int dir_index = sample->Get_Biggest_Fraction_Index ();
  232. if (sample->Sample_Status ((VisDirType)dir_index) != VIS_STATUS_OK) {
  233. bad_points ++;
  234. }
  235. }
  236. //
  237. // Set the dialog text fields
  238. //
  239. int points = ::Get_Scene_Editor ()->Get_Total_Vis_Points ();
  240. SetDlgItemInt (IDC_VIS_POINTS, points);
  241. SetDlgItemInt (IDC_BAD_POINTS, bad_points);
  242. SetDlgItemInt (IDC_MAX_POINTS, max);
  243. int bad_percent = (points > 0) ? ((bad_points * 100) / points) : 0;
  244. CString message;
  245. message.Format ("%d %%", bad_percent);
  246. SetDlgItemText (IDC_PERCENT_BAD, message);
  247. m_CurrentPoint = 0;
  248. m_CurrentMinPoint = 0;
  249. m_CurrentMaxPoint = 0;
  250. On_Graph_Sel_Changed ();
  251. return ;
  252. }
  253. /////////////////////////////////////////////////////////////////////////////
  254. //
  255. // Refresh_View
  256. //
  257. /////////////////////////////////////////////////////////////////////////////
  258. void
  259. VisErrorReportDialogClass::Refresh_View (void)
  260. {
  261. if (m_hWnd != NULL) {
  262. InvalidateRect (&m_GraphArea, FALSE);
  263. UpdateWindow ();
  264. }
  265. return ;
  266. }
  267. /////////////////////////////////////////////////////////////////////////////
  268. //
  269. // OnPaint
  270. //
  271. /////////////////////////////////////////////////////////////////////////////
  272. void
  273. VisErrorReportDialogClass::OnPaint (void)
  274. {
  275. CPaintDC dc(this);
  276. m_Graph.Render (dc, m_GraphArea.left, m_GraphArea.top);
  277. Paint_Axis_Area (dc);
  278. return ;
  279. }
  280. /////////////////////////////////////////////////////////////////////////////
  281. //
  282. // OnVScroll
  283. //
  284. /////////////////////////////////////////////////////////////////////////////
  285. void
  286. VisErrorReportDialogClass::OnVScroll
  287. (
  288. UINT nSBCode,
  289. UINT nPos,
  290. CScrollBar *pScrollBar
  291. )
  292. {
  293. // Reset the range of values in the y-axis
  294. int max = m_TotalPoints - (m_ZoomSlider.GetPos () - 2);
  295. m_Graph.Set_Y_Axis_Range (0, max);
  296. SetDlgItemInt (IDC_MAX_POINTS, max);
  297. //
  298. // Repaint the graph
  299. //
  300. Refresh_View ();
  301. CDialog::OnVScroll (nSBCode, nPos, pScrollBar);
  302. return ;
  303. }
  304. /////////////////////////////////////////////////////////////////////////////
  305. //
  306. // OnLButtonDown
  307. //
  308. /////////////////////////////////////////////////////////////////////////////
  309. void
  310. VisErrorReportDialogClass::OnLButtonDown (UINT nFlags, CPoint point)
  311. {
  312. if (m_GraphArea.PtInRect (point)) {
  313. m_TrackPixel = point.x - m_GraphArea.left;
  314. m_Graph.Set_Selection (m_TrackPixel, m_TrackPixel);
  315. m_bTrackingSel = true;
  316. SetCapture ();
  317. Refresh_View ();
  318. On_Graph_Sel_Changed ();
  319. } else if (m_AxisArea.PtInRect (point)) {
  320. Update_Axis_Area (true);
  321. }
  322. CDialog::OnLButtonDown (nFlags, point);
  323. return ;
  324. }
  325. /////////////////////////////////////////////////////////////////////////////
  326. //
  327. // OnLButtonUp
  328. //
  329. /////////////////////////////////////////////////////////////////////////////
  330. void
  331. VisErrorReportDialogClass::OnLButtonUp (UINT nFlags, CPoint point)
  332. {
  333. if (m_bTrackingSel) {
  334. m_bTrackingSel = false;
  335. ReleaseCapture ();
  336. }
  337. CDialog::OnLButtonUp (nFlags, point);
  338. return ;
  339. }
  340. /////////////////////////////////////////////////////////////////////////////
  341. //
  342. // OnMouseMove
  343. //
  344. /////////////////////////////////////////////////////////////////////////////
  345. void
  346. VisErrorReportDialogClass::OnMouseMove (UINT nFlags, CPoint point)
  347. {
  348. if (m_bTrackingSel) {
  349. int new_pixel = point.x - m_GraphArea.left;
  350. new_pixel = max (new_pixel, 0);
  351. new_pixel = min (new_pixel, m_GraphArea.right-1);
  352. m_Graph.Set_Selection (m_TrackPixel, new_pixel);
  353. Refresh_View ();
  354. On_Graph_Sel_Changed ();
  355. }
  356. CDialog::OnMouseMove (nFlags, point);
  357. return ;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. //
  361. // Display_Point
  362. //
  363. /////////////////////////////////////////////////////////////////////////////
  364. void
  365. VisErrorReportDialogClass::Display_Point (const Matrix3D &transform, bool fly_to)
  366. {
  367. if (fly_to) {
  368. ::Get_Camera_Mgr ()->Fly_To_Transform (transform);
  369. } else {
  370. ::Get_Camera_Mgr ()->Set_Transform (transform);
  371. }
  372. ::Refresh_Main_View ();
  373. return ;
  374. }
  375. //////////////////////////////////////////////////////////////////////////////////
  376. //
  377. // Free_Point_List
  378. //
  379. //////////////////////////////////////////////////////////////////////////////////
  380. void
  381. VisErrorReportDialogClass::Free_Point_List (void)
  382. {
  383. //
  384. // Delete all the vis samples
  385. //
  386. for (int index = 0; index < m_PointList.Count (); index ++) {
  387. VisSampleClass *vis_sample = m_PointList[index];
  388. SAFE_DELETE (vis_sample);
  389. }
  390. m_PointList.Delete_All ();
  391. return ;
  392. }
  393. //////////////////////////////////////////////////////////////////////////////////
  394. //
  395. // Add_Point
  396. //
  397. //////////////////////////////////////////////////////////////////////////////////
  398. void
  399. VisErrorReportDialogClass::Add_Point (const VisSampleClass &point)
  400. {
  401. int start = 0;
  402. int end = m_PointList.Count ();
  403. end = max (end, 0);
  404. float fraction = point.Get_Biggest_Fraction ();
  405. int index = end;
  406. while (end > start)
  407. {
  408. index = start + ((end - start) >> 1);
  409. float curr_fraction = m_PointList[index]->Get_Biggest_Fraction ();
  410. if (fraction > curr_fraction) {
  411. if (start == index) { index ++; break; }
  412. start = index;
  413. } else if (fraction < curr_fraction) {
  414. if (end == index) { index --; break; }
  415. end = index;
  416. } else {
  417. break;
  418. }
  419. }
  420. ASSERT (index >=0 );
  421. //
  422. // Simple binary search to find the right place
  423. // to insert the new data point
  424. //
  425. /*while (end > start) {
  426. int index = start + ((end - start) >> 1);
  427. float curr_fraction = m_PointList[index]->BackfaceFraction;
  428. if ((index == start) || (fraction == curr_fraction)) {
  429. break;
  430. } else if (fraction > curr_fraction) {
  431. start = index;
  432. } else if (fraction < curr_fraction) {
  433. end = index;
  434. }
  435. }*/
  436. //
  437. // Insert the new point into the list
  438. //
  439. m_PointList.Insert (index, new VisSampleClass (point));
  440. return ;
  441. }
  442. /////////////////////////////////////////////////////////////////////////////
  443. //
  444. // Find_Value_Index
  445. //
  446. /////////////////////////////////////////////////////////////////////////////
  447. int
  448. VisErrorReportDialogClass::Find_Value_Index (float fraction)
  449. {
  450. /*int retval = -1;
  451. //
  452. // Simple binary search to find the right place
  453. // to insert the new data point
  454. //
  455. int start = 0;
  456. int end = m_PointList.Count () - 1;
  457. while ((end > start) && (retval == -1)) {
  458. int index = start + ((end - start) >> 1);
  459. float curr_fraction = m_PointList[index]->BackfaceFraction;
  460. if (index == start) {
  461. retval = (fraction > curr_fraction) ? end : start;
  462. break;
  463. } else if (fraction > curr_fraction) {
  464. start = index;
  465. } else if (fraction < curr_fraction) {
  466. end = index;
  467. } else {
  468. retval = index;
  469. }
  470. }
  471. if (retval == -1) {
  472. retval = start;
  473. }*/
  474. int start = 0;
  475. int end = m_PointList.Count ();
  476. end = max (end, 0);
  477. int index = end;
  478. while (end > start)
  479. {
  480. index = start + ((end - start) >> 1);
  481. float curr_fraction = m_PointList[index]->Get_Biggest_Fraction ();
  482. if (fraction > curr_fraction) {
  483. if (start == index) { index ++; break; }
  484. start = index;
  485. } else if (fraction < curr_fraction) {
  486. if (end == index) { index --; break; }
  487. end = index;
  488. } else {
  489. while ((curr_fraction == fraction) && (index > 0)) {
  490. curr_fraction = m_PointList[--index]->Get_Biggest_Fraction ();
  491. }
  492. index = (curr_fraction == fraction) ? index : index + 1;
  493. //m_ValueList[index].count ++;
  494. //found = true;
  495. break;
  496. }
  497. }
  498. ASSERT (index >=0 );
  499. return index;
  500. }
  501. //////////////////////////////////////////////////////////////////////////////////
  502. //
  503. // On_Graph_Sel_Changed
  504. //
  505. //////////////////////////////////////////////////////////////////////////////////
  506. void
  507. VisErrorReportDialogClass::On_Graph_Sel_Changed (void)
  508. {
  509. float range_min = 0;
  510. float range_max = 0;
  511. m_Graph.Get_Selection (range_min, range_max);
  512. if (range_min >= 0 && range_max >= 0) {
  513. m_SelStartIndex = Find_Value_Index (range_min);
  514. m_SelEndIndex = Find_Value_Index (range_max);
  515. } else {
  516. m_SelStartIndex = 0;
  517. m_SelEndIndex = m_PointList.Count () - 1;
  518. m_SelEndIndex = max (m_SelEndIndex, 0);
  519. }
  520. m_CurrentPoint = m_SelStartIndex - 1;
  521. //
  522. // Update the dialog UI
  523. //
  524. Update_Current_Point_Text ();
  525. Update_Nav_Buttons ();
  526. return ;
  527. }
  528. //////////////////////////////////////////////////////////////////////////////////
  529. //
  530. // Update_Nav_Buttons
  531. //
  532. //////////////////////////////////////////////////////////////////////////////////
  533. void
  534. VisErrorReportDialogClass::Update_Nav_Buttons (void)
  535. {
  536. bool enable_prev = m_CurrentPoint > m_SelStartIndex;
  537. bool enable_next = (m_CurrentPoint < m_SelEndIndex) && (m_PointList.Count () > 0);
  538. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_PREV_ERROR), enable_prev);
  539. ::EnableWindow (::GetDlgItem (m_hWnd, IDC_NEXT_ERROR), enable_next);
  540. return ;
  541. }
  542. //////////////////////////////////////////////////////////////////////////////////
  543. //
  544. // OnPrevError
  545. //
  546. //////////////////////////////////////////////////////////////////////////////////
  547. void
  548. VisErrorReportDialogClass::OnPrevError (void)
  549. {
  550. if (m_CurrentPoint > m_SelEndIndex) {
  551. m_CurrentPoint = m_SelEndIndex;
  552. } else {
  553. m_CurrentPoint --;
  554. m_CurrentPoint = max (m_CurrentPoint, 0);
  555. }
  556. //
  557. // Show the point
  558. //
  559. if (m_CurrentPoint < m_PointList.Count ()) {
  560. VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
  561. int index = vis_sample->Get_Biggest_Fraction_Index ();
  562. vis_sample->Set_Cur_Direction ((VisDirType)index);
  563. Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), true);
  564. }
  565. //
  566. // Update the UI
  567. //
  568. Update_Current_Point_Text ();
  569. Update_Nav_Buttons ();
  570. return ;
  571. }
  572. //////////////////////////////////////////////////////////////////////////////////
  573. //
  574. // OnNextError
  575. //
  576. //////////////////////////////////////////////////////////////////////////////////
  577. void
  578. VisErrorReportDialogClass::OnNextError (void)
  579. {
  580. if (m_CurrentPoint < m_SelStartIndex) {
  581. m_CurrentPoint = m_SelStartIndex;
  582. } else {
  583. m_CurrentPoint ++;
  584. m_CurrentPoint = min (m_CurrentPoint, m_PointList.Count () - 1);
  585. }
  586. //
  587. // Show the point
  588. //
  589. if (m_CurrentPoint < m_PointList.Count ()) {
  590. VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
  591. int index = vis_sample->Get_Biggest_Fraction_Index ();
  592. vis_sample->Set_Cur_Direction ((VisDirType)index);
  593. Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), true);
  594. }
  595. //
  596. // Update the UI
  597. //
  598. Update_Current_Point_Text ();
  599. Update_Nav_Buttons ();
  600. return ;
  601. }
  602. //////////////////////////////////////////////////////////////////////////////////
  603. //
  604. // Update_Current_Point_Text
  605. //
  606. //////////////////////////////////////////////////////////////////////////////////
  607. void
  608. VisErrorReportDialogClass::Update_Current_Point_Text (void)
  609. {
  610. //
  611. // Update the point-range static text control
  612. //
  613. int current_point = max ((m_CurrentPoint - m_SelStartIndex) + 1, 0);
  614. CString message;
  615. message.Format ("%d of %d", current_point, m_SelEndIndex - m_SelStartIndex);
  616. SetDlgItemText (IDC_CURRENT_POINT, message);
  617. if ((m_CurrentPoint >= 0) &&
  618. (m_CurrentPoint < m_PointList.Count ()))
  619. {
  620. VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
  621. //
  622. // Update the backface percent for this sample
  623. //
  624. float fraction = vis_sample->Get_Biggest_Fraction ();
  625. message.Format ("%.2f %%", fraction * 100);
  626. SetDlgItemText (IDC_CURRENT_PERCENT, message);
  627. //
  628. // Get the status string for the current direction
  629. //
  630. int dir_index = vis_sample->Get_Cur_Direction ();
  631. switch (vis_sample->Sample_Status ((VisDirType)dir_index)) {
  632. case VIS_STATUS_OK:
  633. message = "Ok";
  634. break;
  635. case VIS_STATUS_NOT_TAKEN:
  636. message = "Not Taken";
  637. break;
  638. case VIS_STATUS_ERROR:
  639. message = "!!Error!!";
  640. break;
  641. case VIS_STATUS_BACKFACE_LEAK:
  642. message = "Leak";
  643. break;
  644. case VIS_STATUS_BACKFACE_OVERFLOW:
  645. message = "Overflow";
  646. break;
  647. }
  648. SetDlgItemText (IDC_CURRENT_POINT_STATUS, message);
  649. } else {
  650. SetDlgItemText (IDC_CURRENT_PERCENT, "");
  651. SetDlgItemText (IDC_CURRENT_POINT_STATUS, "");
  652. }
  653. return ;
  654. }
  655. /////////////////////////////////////////////////////////////////////////////
  656. //
  657. // OnDrawItem
  658. //
  659. /////////////////////////////////////////////////////////////////////////////
  660. void
  661. VisErrorReportDialogClass::OnDrawItem
  662. (
  663. int nIDCtl,
  664. LPDRAWITEMSTRUCT lpDrawItemStruct
  665. )
  666. {
  667. //
  668. // Determine what state to draw the button in (pushed or normal)
  669. //
  670. UINT state = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
  671. POINT offset = { 0 };
  672. if (lpDrawItemStruct->itemState & ODS_SELECTED) {
  673. state |= DFCS_PUSHED;
  674. offset.x = 1;
  675. offset.y = 1;
  676. }
  677. // Draw the button's outline
  678. CRect rect = lpDrawItemStruct->rcItem;
  679. ::DrawFrameControl (lpDrawItemStruct->hDC, rect, DFC_BUTTON, state);
  680. //
  681. // Determine which BMP to use
  682. //
  683. HBITMAP hbmp = NULL;
  684. if (nIDCtl == IDC_PREV_ERROR) {
  685. hbmp = ::IsWindowEnabled (lpDrawItemStruct->hwndItem) ? m_PrevButton.normal : m_PrevButton.disabled;
  686. } else if (nIDCtl == IDC_NEXT_ERROR) {
  687. hbmp = ::IsWindowEnabled (lpDrawItemStruct->hwndItem) ? m_NextButton.normal : m_NextButton.disabled;
  688. }
  689. HDC mem_dc = ::CreateCompatibleDC (NULL);
  690. HBITMAP old_bmp = (HBITMAP)::SelectObject (mem_dc, hbmp);
  691. //
  692. // Draw the BMP centered in the button
  693. //
  694. const int BMP_WIDTH = 25;
  695. const int BMP_HEIGHT = 28;
  696. int x_pos = rect.left + (rect.Width () >> 1) - (BMP_WIDTH >> 1) + offset.x;
  697. int y_pos = rect.top + (rect.Height () >> 1) - (BMP_HEIGHT >> 1) + offset.y;
  698. ::BitBlt (lpDrawItemStruct->hDC, x_pos, y_pos, BMP_WIDTH, BMP_HEIGHT, mem_dc, 0, 0, SRCCOPY);
  699. ::SelectObject (mem_dc, old_bmp);
  700. ::DeleteDC (mem_dc);
  701. // Draw the focus rectangle if necessary
  702. if (lpDrawItemStruct->itemState & ODS_FOCUS) {
  703. ::DrawFocusRect (lpDrawItemStruct->hDC, &rect);
  704. }
  705. // Allow the base class to process this message
  706. CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
  707. return ;
  708. }
  709. /////////////////////////////////////////////////////////////////////////////
  710. //
  711. // Paint_Axis_Area
  712. //
  713. /////////////////////////////////////////////////////////////////////////////
  714. void
  715. VisErrorReportDialogClass::Paint_Axis_Area (HDC hdc)
  716. {
  717. HDC mem_dc = ::CreateCompatibleDC (NULL);
  718. HBITMAP old_bmp = (HBITMAP)::SelectObject (mem_dc, m_AxisBMP);
  719. //
  720. // Draw the BMP centered in the button
  721. //
  722. const int BMP_WIDTH = 65;
  723. const int BMP_HEIGHT = 65;
  724. //int x_pos = m_AxisArea.left + (m_AxisArea.Width () >> 1) - (BMP_WIDTH >> 1);
  725. //int y_pos = m_AxisArea.top + (m_AxisArea.Height () >> 1) - (BMP_HEIGHT >> 1);
  726. ::BitBlt (hdc, m_AxisArea.left, m_AxisArea.top, BMP_WIDTH, BMP_HEIGHT, mem_dc, 0, 0, SRCCOPY);
  727. ::SelectObject (mem_dc, old_bmp);
  728. old_bmp = (HBITMAP)::SelectObject (mem_dc, m_AxisSelBMP);
  729. //
  730. // Paint the selected areas of the axis
  731. //
  732. for (int index = 0; index < 6; index ++) {
  733. if (m_AxisSel & (1 << index)) {
  734. CRect &rect = m_AxisSelAreas[index];
  735. int x_pos = m_AxisArea.left + rect.left;
  736. int y_pos = m_AxisArea.top + rect.top;
  737. ::BitBlt (hdc, x_pos, y_pos, rect.Width (), rect.Height (), mem_dc, rect.left, rect.top, SRCCOPY);
  738. }
  739. }
  740. ::SelectObject (mem_dc, old_bmp);
  741. ::DeleteDC (mem_dc);
  742. return ;
  743. }
  744. UINT VisErrorReportDialogClass::OnNcHitTest(CPoint point)
  745. {
  746. // TODO: Add your message handler code here and/or call default
  747. return CDialog::OnNcHitTest(point);
  748. }
  749. /////////////////////////////////////////////////////////////////////////////
  750. //
  751. // OnSetCursor
  752. //
  753. /////////////////////////////////////////////////////////////////////////////
  754. BOOL
  755. VisErrorReportDialogClass::OnSetCursor
  756. (
  757. CWnd * pwnd,
  758. UINT hit_test,
  759. UINT message
  760. )
  761. {
  762. BOOL retval = FALSE;
  763. //
  764. // Determine if the cursor is over a 'hot-spot' in the axis area.
  765. //
  766. if (Update_Axis_Area ()) {
  767. ::SetCursor (::LoadCursor (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDC_HAND_POINTER)));
  768. } else {
  769. retval = CDialog::OnSetCursor (pwnd, hit_test, message);
  770. }
  771. return retval;
  772. }
  773. /////////////////////////////////////////////////////////////////////////////
  774. //
  775. // Update_Axis_Area
  776. //
  777. /////////////////////////////////////////////////////////////////////////////
  778. bool
  779. VisErrorReportDialogClass::Update_Axis_Area (bool do_view_change)
  780. {
  781. CPoint point;
  782. ::GetCursorPos (&point);
  783. ScreenToClient (&point);
  784. point.x -= m_AxisArea.left;
  785. point.y -= m_AxisArea.top;
  786. bool found = false;
  787. int old_sel = m_AxisSel;
  788. m_AxisSel = 0;
  789. //
  790. // Only do the UI stuff if we have a current point.
  791. //
  792. if ((m_CurrentPoint >= 0) &&
  793. (m_CurrentPoint < m_PointList.Count ()))
  794. {
  795. VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
  796. if ((point.x >= 0) && (point.y >= 0)) {
  797. //
  798. // Determine which direction we are over (if any)
  799. //
  800. for (int index = 0; index < 6 && !found; index ++) {
  801. if (m_AxisSelAreas[index].PtInRect (point)) {
  802. m_AxisSel |= (1 << index);
  803. found = true;
  804. //
  805. // Update the camera if necessary
  806. //
  807. if (do_view_change) {
  808. vis_sample->Set_Cur_Direction ((VisDirType)index);
  809. Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), false);
  810. }
  811. }
  812. }
  813. }
  814. //
  815. // Hilight the direction that is currently displayed
  816. //
  817. int direction = vis_sample->Get_Cur_Direction ();
  818. int bit = (1 << direction);
  819. m_AxisSel |= bit;
  820. }
  821. if (old_sel != m_AxisSel) {
  822. //
  823. // Repaint the axis area
  824. //
  825. HDC hdc = ::GetDC (m_hWnd);
  826. Paint_Axis_Area (hdc);
  827. ::ReleaseDC (m_hWnd, hdc);
  828. }
  829. return found;
  830. }
  831. /////////////////////////////////////////////////////////////////////////////
  832. //
  833. // OnDestroy
  834. //
  835. /////////////////////////////////////////////////////////////////////////////
  836. void
  837. VisErrorReportDialogClass::OnDestroy (void)
  838. {
  839. CDialog::OnDestroy();
  840. ::RemoveProp (m_hWnd, "ALLOW_UPDATE");
  841. return ;
  842. }