This repository has been archived on 2025-02-27. You can view files and clone it, but cannot push or open issues or pull requests.
CnC_Renegade/Code/Tools/LevelEdit/VisErrorReportDialog.cpp

992 lines
25 KiB
C++

/*
** Command & Conquer Renegade(tm)
** Copyright 2025 Electronic Arts Inc.
**
** This program is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
// VisErrorReportDialog.cpp : implementation file
//
#include "StdAfx.H"
#include "LevelEdit.H"
#include "VisErrorReportDialog.H"
#include "Utils.H"
#include "VisLog.H"
#include "SceneEditor.H"
#include "CameraMgr.H"
#include "phys.h"
#include "rendobj.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
//
// Constants
//
/////////////////////////////////////////////////////////////////////////////
static const int AXIS_BMP_WIDTH = 65;
static const int AXIS_BMP_HEIGHT = 65;
/////////////////////////////////////////////////////////////////////////////
//
// Local Inlines
//
/////////////////////////////////////////////////////////////////////////////
static inline HBITMAP Load_Bitmap (UINT res_id)
{
return (HBITMAP)::LoadImage (::AfxGetResourceHandle (), MAKEINTRESOURCE (res_id), IMAGE_BITMAP, 0, 0, LR_LOADTRANSPARENT);
}
/////////////////////////////////////////////////////////////////////////////
//
// VisErrorReportDialogClass
//
/////////////////////////////////////////////////////////////////////////////
VisErrorReportDialogClass::VisErrorReportDialogClass (CWnd *pParent)
: m_CurrentPoint (0),
m_GraphArea (0, 0, 0, 0),
m_AxisArea (0, 0, 0, 0),
m_CurrentMinPoint (0),
m_CurrentMaxPoint (0),
m_TotalPoints (0),
m_bTrackingSel (false),
m_TrackPixel (0),
m_SelStartIndex (0),
m_SelEndIndex (0),
m_AxisBMP (NULL),
m_AxisSelBMP (NULL),
m_AxisSel (0),
CDialog(VisErrorReportDialogClass::IDD, pParent)
{
//{{AFX_DATA_INIT(VisErrorReportDialogClass)
// NOTE: the ClassWizard will add member initialization here
//}}AFX_DATA_INIT
m_PrevButton.normal = Load_Bitmap (IDB_LT_ARROW);
m_PrevButton.disabled = Load_Bitmap (IDB_LT_ARROW_D);
m_NextButton.normal = Load_Bitmap (IDB_RT_ARROW);
m_NextButton.disabled = Load_Bitmap (IDB_RT_ARROW_D);
m_AxisBMP = Load_Bitmap (IDB_AXIS_BMP);
m_AxisSelBMP = Load_Bitmap (IDB_AXIS_SEL_BMP);
m_AxisSelAreas[VIS_FORWARD].left = 1;
m_AxisSelAreas[VIS_FORWARD].top = 38;
m_AxisSelAreas[VIS_FORWARD].right = m_AxisSelAreas[VIS_FORWARD].left + 20;
m_AxisSelAreas[VIS_FORWARD].bottom = m_AxisSelAreas[VIS_FORWARD].top + 16;
m_AxisSelAreas[VIS_LEFT].left = 1;
m_AxisSelAreas[VIS_LEFT].top = 12;
m_AxisSelAreas[VIS_LEFT].right = m_AxisSelAreas[VIS_LEFT].left + 20;
m_AxisSelAreas[VIS_LEFT].bottom = m_AxisSelAreas[VIS_LEFT].top + 16;
m_AxisSelAreas[VIS_BACKWARDS].left = 42;
m_AxisSelAreas[VIS_BACKWARDS].top = 13;
m_AxisSelAreas[VIS_BACKWARDS].right = m_AxisSelAreas[VIS_BACKWARDS].left + 20;
m_AxisSelAreas[VIS_BACKWARDS].bottom = m_AxisSelAreas[VIS_BACKWARDS].top + 16;
m_AxisSelAreas[VIS_RIGHT].left = 42;
m_AxisSelAreas[VIS_RIGHT].top = 39;
m_AxisSelAreas[VIS_RIGHT].right = m_AxisSelAreas[VIS_RIGHT].left + 20;
m_AxisSelAreas[VIS_RIGHT].bottom = m_AxisSelAreas[VIS_RIGHT].top + 16;
m_AxisSelAreas[VIS_UP].left = 21;
m_AxisSelAreas[VIS_UP].top = 1;
m_AxisSelAreas[VIS_UP].right = m_AxisSelAreas[VIS_UP].left + 20;
m_AxisSelAreas[VIS_UP].bottom = m_AxisSelAreas[VIS_UP].top + 16;
m_AxisSelAreas[VIS_DOWN].left = 22;
m_AxisSelAreas[VIS_DOWN].top = 47;
m_AxisSelAreas[VIS_DOWN].right = m_AxisSelAreas[VIS_DOWN].left + 20;
m_AxisSelAreas[VIS_DOWN].bottom = m_AxisSelAreas[VIS_DOWN].top + 16;
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// ~VisErrorReportDialogClass
//
/////////////////////////////////////////////////////////////////////////////
VisErrorReportDialogClass::~VisErrorReportDialogClass (void)
{
//
// Free the BMPs
//
if (m_PrevButton.normal) ::DeleteObject (m_PrevButton.normal);
if (m_PrevButton.disabled) ::DeleteObject (m_PrevButton.disabled);
if (m_NextButton.normal) ::DeleteObject (m_NextButton.normal);
if (m_NextButton.disabled) ::DeleteObject (m_NextButton.disabled);
Free_Point_List ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// DoDataExchange
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::DoDataExchange (CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(VisErrorReportDialogClass)
DDX_Control(pDX, IDC_ZOOM_SLIDER, m_ZoomSlider);
//}}AFX_DATA_MAP
return ;
}
BEGIN_MESSAGE_MAP(VisErrorReportDialogClass, CDialog)
//{{AFX_MSG_MAP(VisErrorReportDialogClass)
ON_WM_PAINT()
ON_WM_VSCROLL()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_BN_CLICKED(IDC_PREV_ERROR, OnPrevError)
ON_BN_CLICKED(IDC_NEXT_ERROR, OnNextError)
ON_WM_DRAWITEM()
ON_WM_NCHITTEST()
ON_WM_SETCURSOR()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
//
// OnInitDialog
//
/////////////////////////////////////////////////////////////////////////////
BOOL
VisErrorReportDialogClass::OnInitDialog (void)
{
CDialog::OnInitDialog ();
//
// Register this window for timer-based screen refreshing
//
::SetProp (m_hWnd, "ALLOW_UPDATE", (HANDLE)1);
//
// Set the dimensions of the graph area
//
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_HISTOGRAM), &m_GraphArea);
ScreenToClient (&m_GraphArea);
m_GraphArea.left ++;
m_GraphArea.right --;
m_GraphArea.top ++;
m_GraphArea.bottom --;
m_Graph.Set_Dimensions (m_GraphArea.Width (), m_GraphArea.Height ());
//
// Set the dimensions of the 'axis' area.
//
CRect rect;
::GetWindowRect (::GetDlgItem (m_hWnd, IDC_AXIS_AREA), &rect);
ScreenToClient (&rect);
rect.left ++;
rect.right --;
rect.top ++;
rect.bottom --;
m_AxisArea.left = rect.left + (rect.Width () >> 1) - (AXIS_BMP_WIDTH >> 1);
m_AxisArea.top = rect.top + (rect.Height () >> 1) - (AXIS_BMP_HEIGHT >> 1);
m_AxisArea.right = m_AxisArea.left + AXIS_BMP_WIDTH;
m_AxisArea.bottom = m_AxisArea.top + AXIS_BMP_HEIGHT;
// Update the dialog with data from the scene
Re_Sync_Data ();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////
//
// Re_Sync_Data
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Re_Sync_Data (void)
{
//
// Get the error list from the scene
//
VisLogClass &vis_log = ::Get_Scene_Editor ()->Get_Vis_Log ();
VIS_SAMPLE_LIST &error_list = vis_log.Peek_Error_List ();
m_TotalPoints = error_list.Count ();
//
// Setup the 'zoom' slider
//
m_ZoomSlider.SetRange (2, m_TotalPoints >> 1);
m_ZoomSlider.SetPos (m_TotalPoints >> 2);
// Reset the range of values in the y-axis
int max = (m_TotalPoints >> 1) - (m_ZoomSlider.GetPos () - 2);
m_Graph.Set_Y_Axis_Range (0, max);
//
// Add the vis error points to the graph
//
Free_Point_List ();
int bad_points = 0;
for (int index = 0; index < error_list.Count (); index ++) {
VisSampleClass *sample = error_list[index];
Add_Point (*sample);
//
// Determining which direction resulted in the largest backface fraction
//
float fraction = sample->Get_Biggest_Fraction ();
m_Graph.Add_Data_Point (fraction);
//
// Determine if this point was bad or not
//
int dir_index = sample->Get_Biggest_Fraction_Index ();
if (sample->Sample_Status ((VisDirType)dir_index) != VIS_STATUS_OK) {
bad_points ++;
}
}
//
// Set the dialog text fields
//
int points = ::Get_Scene_Editor ()->Get_Total_Vis_Points ();
SetDlgItemInt (IDC_VIS_POINTS, points);
SetDlgItemInt (IDC_BAD_POINTS, bad_points);
SetDlgItemInt (IDC_MAX_POINTS, max);
int bad_percent = (points > 0) ? ((bad_points * 100) / points) : 0;
CString message;
message.Format ("%d %%", bad_percent);
SetDlgItemText (IDC_PERCENT_BAD, message);
m_CurrentPoint = 0;
m_CurrentMinPoint = 0;
m_CurrentMaxPoint = 0;
On_Graph_Sel_Changed ();
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Refresh_View
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Refresh_View (void)
{
if (m_hWnd != NULL) {
InvalidateRect (&m_GraphArea, FALSE);
UpdateWindow ();
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnPaint
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnPaint (void)
{
CPaintDC dc(this);
m_Graph.Render (dc, m_GraphArea.left, m_GraphArea.top);
Paint_Axis_Area (dc);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnVScroll
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnVScroll
(
UINT nSBCode,
UINT nPos,
CScrollBar *pScrollBar
)
{
// Reset the range of values in the y-axis
int max = m_TotalPoints - (m_ZoomSlider.GetPos () - 2);
m_Graph.Set_Y_Axis_Range (0, max);
SetDlgItemInt (IDC_MAX_POINTS, max);
//
// Repaint the graph
//
Refresh_View ();
CDialog::OnVScroll (nSBCode, nPos, pScrollBar);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonDown
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnLButtonDown (UINT nFlags, CPoint point)
{
if (m_GraphArea.PtInRect (point)) {
m_TrackPixel = point.x - m_GraphArea.left;
m_Graph.Set_Selection (m_TrackPixel, m_TrackPixel);
m_bTrackingSel = true;
SetCapture ();
Refresh_View ();
On_Graph_Sel_Changed ();
} else if (m_AxisArea.PtInRect (point)) {
Update_Axis_Area (true);
}
CDialog::OnLButtonDown (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnLButtonUp
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnLButtonUp (UINT nFlags, CPoint point)
{
if (m_bTrackingSel) {
m_bTrackingSel = false;
ReleaseCapture ();
}
CDialog::OnLButtonUp (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnMouseMove
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnMouseMove (UINT nFlags, CPoint point)
{
if (m_bTrackingSel) {
int new_pixel = point.x - m_GraphArea.left;
new_pixel = max (new_pixel, 0);
new_pixel = min (new_pixel, m_GraphArea.right-1);
m_Graph.Set_Selection (m_TrackPixel, new_pixel);
Refresh_View ();
On_Graph_Sel_Changed ();
}
CDialog::OnMouseMove (nFlags, point);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Display_Point
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Display_Point (const Matrix3D &transform, bool fly_to)
{
if (fly_to) {
::Get_Camera_Mgr ()->Fly_To_Transform (transform);
} else {
::Get_Camera_Mgr ()->Set_Transform (transform);
}
::Refresh_Main_View ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Free_Point_List
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Free_Point_List (void)
{
//
// Delete all the vis samples
//
for (int index = 0; index < m_PointList.Count (); index ++) {
VisSampleClass *vis_sample = m_PointList[index];
SAFE_DELETE (vis_sample);
}
m_PointList.Delete_All ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Add_Point
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Add_Point (const VisSampleClass &point)
{
int start = 0;
int end = m_PointList.Count ();
end = max (end, 0);
float fraction = point.Get_Biggest_Fraction ();
int index = end;
while (end > start)
{
index = start + ((end - start) >> 1);
float curr_fraction = m_PointList[index]->Get_Biggest_Fraction ();
if (fraction > curr_fraction) {
if (start == index) { index ++; break; }
start = index;
} else if (fraction < curr_fraction) {
if (end == index) { index --; break; }
end = index;
} else {
break;
}
}
ASSERT (index >=0 );
//
// Simple binary search to find the right place
// to insert the new data point
//
/*while (end > start) {
int index = start + ((end - start) >> 1);
float curr_fraction = m_PointList[index]->BackfaceFraction;
if ((index == start) || (fraction == curr_fraction)) {
break;
} else if (fraction > curr_fraction) {
start = index;
} else if (fraction < curr_fraction) {
end = index;
}
}*/
//
// Insert the new point into the list
//
m_PointList.Insert (index, new VisSampleClass (point));
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Find_Value_Index
//
/////////////////////////////////////////////////////////////////////////////
int
VisErrorReportDialogClass::Find_Value_Index (float fraction)
{
/*int retval = -1;
//
// Simple binary search to find the right place
// to insert the new data point
//
int start = 0;
int end = m_PointList.Count () - 1;
while ((end > start) && (retval == -1)) {
int index = start + ((end - start) >> 1);
float curr_fraction = m_PointList[index]->BackfaceFraction;
if (index == start) {
retval = (fraction > curr_fraction) ? end : start;
break;
} else if (fraction > curr_fraction) {
start = index;
} else if (fraction < curr_fraction) {
end = index;
} else {
retval = index;
}
}
if (retval == -1) {
retval = start;
}*/
int start = 0;
int end = m_PointList.Count ();
end = max (end, 0);
int index = end;
while (end > start)
{
index = start + ((end - start) >> 1);
float curr_fraction = m_PointList[index]->Get_Biggest_Fraction ();
if (fraction > curr_fraction) {
if (start == index) { index ++; break; }
start = index;
} else if (fraction < curr_fraction) {
if (end == index) { index --; break; }
end = index;
} else {
while ((curr_fraction == fraction) && (index > 0)) {
curr_fraction = m_PointList[--index]->Get_Biggest_Fraction ();
}
index = (curr_fraction == fraction) ? index : index + 1;
//m_ValueList[index].count ++;
//found = true;
break;
}
}
ASSERT (index >=0 );
return index;
}
//////////////////////////////////////////////////////////////////////////////////
//
// On_Graph_Sel_Changed
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::On_Graph_Sel_Changed (void)
{
float range_min = 0;
float range_max = 0;
m_Graph.Get_Selection (range_min, range_max);
if (range_min >= 0 && range_max >= 0) {
m_SelStartIndex = Find_Value_Index (range_min);
m_SelEndIndex = Find_Value_Index (range_max);
} else {
m_SelStartIndex = 0;
m_SelEndIndex = m_PointList.Count () - 1;
m_SelEndIndex = max (m_SelEndIndex, 0);
}
m_CurrentPoint = m_SelStartIndex - 1;
//
// Update the dialog UI
//
Update_Current_Point_Text ();
Update_Nav_Buttons ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Update_Nav_Buttons
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Update_Nav_Buttons (void)
{
bool enable_prev = m_CurrentPoint > m_SelStartIndex;
bool enable_next = (m_CurrentPoint < m_SelEndIndex) && (m_PointList.Count () > 0);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_PREV_ERROR), enable_prev);
::EnableWindow (::GetDlgItem (m_hWnd, IDC_NEXT_ERROR), enable_next);
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// OnPrevError
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnPrevError (void)
{
if (m_CurrentPoint > m_SelEndIndex) {
m_CurrentPoint = m_SelEndIndex;
} else {
m_CurrentPoint --;
m_CurrentPoint = max (m_CurrentPoint, 0);
}
//
// Show the point
//
if (m_CurrentPoint < m_PointList.Count ()) {
VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
int index = vis_sample->Get_Biggest_Fraction_Index ();
vis_sample->Set_Cur_Direction ((VisDirType)index);
Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), true);
}
//
// Update the UI
//
Update_Current_Point_Text ();
Update_Nav_Buttons ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// OnNextError
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnNextError (void)
{
if (m_CurrentPoint < m_SelStartIndex) {
m_CurrentPoint = m_SelStartIndex;
} else {
m_CurrentPoint ++;
m_CurrentPoint = min (m_CurrentPoint, m_PointList.Count () - 1);
}
//
// Show the point
//
if (m_CurrentPoint < m_PointList.Count ()) {
VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
int index = vis_sample->Get_Biggest_Fraction_Index ();
vis_sample->Set_Cur_Direction ((VisDirType)index);
Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), true);
}
//
// Update the UI
//
Update_Current_Point_Text ();
Update_Nav_Buttons ();
return ;
}
//////////////////////////////////////////////////////////////////////////////////
//
// Update_Current_Point_Text
//
//////////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Update_Current_Point_Text (void)
{
//
// Update the point-range static text control
//
int current_point = max ((m_CurrentPoint - m_SelStartIndex) + 1, 0);
CString message;
message.Format ("%d of %d", current_point, m_SelEndIndex - m_SelStartIndex);
SetDlgItemText (IDC_CURRENT_POINT, message);
if ((m_CurrentPoint >= 0) &&
(m_CurrentPoint < m_PointList.Count ()))
{
VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
//
// Update the backface percent for this sample
//
float fraction = vis_sample->Get_Biggest_Fraction ();
message.Format ("%.2f %%", fraction * 100);
SetDlgItemText (IDC_CURRENT_PERCENT, message);
//
// Get the status string for the current direction
//
int dir_index = vis_sample->Get_Cur_Direction ();
switch (vis_sample->Sample_Status ((VisDirType)dir_index)) {
case VIS_STATUS_OK:
message = "Ok";
break;
case VIS_STATUS_NOT_TAKEN:
message = "Not Taken";
break;
case VIS_STATUS_ERROR:
message = "!!Error!!";
break;
case VIS_STATUS_BACKFACE_LEAK:
message = "Leak";
break;
case VIS_STATUS_BACKFACE_OVERFLOW:
message = "Overflow";
break;
}
SetDlgItemText (IDC_CURRENT_POINT_STATUS, message);
} else {
SetDlgItemText (IDC_CURRENT_PERCENT, "");
SetDlgItemText (IDC_CURRENT_POINT_STATUS, "");
}
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDrawItem
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnDrawItem
(
int nIDCtl,
LPDRAWITEMSTRUCT lpDrawItemStruct
)
{
//
// Determine what state to draw the button in (pushed or normal)
//
UINT state = DFCS_BUTTONPUSH | DFCS_ADJUSTRECT;
POINT offset = { 0 };
if (lpDrawItemStruct->itemState & ODS_SELECTED) {
state |= DFCS_PUSHED;
offset.x = 1;
offset.y = 1;
}
// Draw the button's outline
CRect rect = lpDrawItemStruct->rcItem;
::DrawFrameControl (lpDrawItemStruct->hDC, rect, DFC_BUTTON, state);
//
// Determine which BMP to use
//
HBITMAP hbmp = NULL;
if (nIDCtl == IDC_PREV_ERROR) {
hbmp = ::IsWindowEnabled (lpDrawItemStruct->hwndItem) ? m_PrevButton.normal : m_PrevButton.disabled;
} else if (nIDCtl == IDC_NEXT_ERROR) {
hbmp = ::IsWindowEnabled (lpDrawItemStruct->hwndItem) ? m_NextButton.normal : m_NextButton.disabled;
}
HDC mem_dc = ::CreateCompatibleDC (NULL);
HBITMAP old_bmp = (HBITMAP)::SelectObject (mem_dc, hbmp);
//
// Draw the BMP centered in the button
//
const int BMP_WIDTH = 25;
const int BMP_HEIGHT = 28;
int x_pos = rect.left + (rect.Width () >> 1) - (BMP_WIDTH >> 1) + offset.x;
int y_pos = rect.top + (rect.Height () >> 1) - (BMP_HEIGHT >> 1) + offset.y;
::BitBlt (lpDrawItemStruct->hDC, x_pos, y_pos, BMP_WIDTH, BMP_HEIGHT, mem_dc, 0, 0, SRCCOPY);
::SelectObject (mem_dc, old_bmp);
::DeleteDC (mem_dc);
// Draw the focus rectangle if necessary
if (lpDrawItemStruct->itemState & ODS_FOCUS) {
::DrawFocusRect (lpDrawItemStruct->hDC, &rect);
}
// Allow the base class to process this message
CDialog::OnDrawItem(nIDCtl, lpDrawItemStruct);
return ;
}
/////////////////////////////////////////////////////////////////////////////
//
// Paint_Axis_Area
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::Paint_Axis_Area (HDC hdc)
{
HDC mem_dc = ::CreateCompatibleDC (NULL);
HBITMAP old_bmp = (HBITMAP)::SelectObject (mem_dc, m_AxisBMP);
//
// Draw the BMP centered in the button
//
const int BMP_WIDTH = 65;
const int BMP_HEIGHT = 65;
//int x_pos = m_AxisArea.left + (m_AxisArea.Width () >> 1) - (BMP_WIDTH >> 1);
//int y_pos = m_AxisArea.top + (m_AxisArea.Height () >> 1) - (BMP_HEIGHT >> 1);
::BitBlt (hdc, m_AxisArea.left, m_AxisArea.top, BMP_WIDTH, BMP_HEIGHT, mem_dc, 0, 0, SRCCOPY);
::SelectObject (mem_dc, old_bmp);
old_bmp = (HBITMAP)::SelectObject (mem_dc, m_AxisSelBMP);
//
// Paint the selected areas of the axis
//
for (int index = 0; index < 6; index ++) {
if (m_AxisSel & (1 << index)) {
CRect &rect = m_AxisSelAreas[index];
int x_pos = m_AxisArea.left + rect.left;
int y_pos = m_AxisArea.top + rect.top;
::BitBlt (hdc, x_pos, y_pos, rect.Width (), rect.Height (), mem_dc, rect.left, rect.top, SRCCOPY);
}
}
::SelectObject (mem_dc, old_bmp);
::DeleteDC (mem_dc);
return ;
}
UINT VisErrorReportDialogClass::OnNcHitTest(CPoint point)
{
// TODO: Add your message handler code here and/or call default
return CDialog::OnNcHitTest(point);
}
/////////////////////////////////////////////////////////////////////////////
//
// OnSetCursor
//
/////////////////////////////////////////////////////////////////////////////
BOOL
VisErrorReportDialogClass::OnSetCursor
(
CWnd * pwnd,
UINT hit_test,
UINT message
)
{
BOOL retval = FALSE;
//
// Determine if the cursor is over a 'hot-spot' in the axis area.
//
if (Update_Axis_Area ()) {
::SetCursor (::LoadCursor (::AfxGetResourceHandle (), MAKEINTRESOURCE (IDC_HAND_POINTER)));
} else {
retval = CDialog::OnSetCursor (pwnd, hit_test, message);
}
return retval;
}
/////////////////////////////////////////////////////////////////////////////
//
// Update_Axis_Area
//
/////////////////////////////////////////////////////////////////////////////
bool
VisErrorReportDialogClass::Update_Axis_Area (bool do_view_change)
{
CPoint point;
::GetCursorPos (&point);
ScreenToClient (&point);
point.x -= m_AxisArea.left;
point.y -= m_AxisArea.top;
bool found = false;
int old_sel = m_AxisSel;
m_AxisSel = 0;
//
// Only do the UI stuff if we have a current point.
//
if ((m_CurrentPoint >= 0) &&
(m_CurrentPoint < m_PointList.Count ()))
{
VisSampleClass *vis_sample = m_PointList[m_CurrentPoint];
if ((point.x >= 0) && (point.y >= 0)) {
//
// Determine which direction we are over (if any)
//
for (int index = 0; index < 6 && !found; index ++) {
if (m_AxisSelAreas[index].PtInRect (point)) {
m_AxisSel |= (1 << index);
found = true;
//
// Update the camera if necessary
//
if (do_view_change) {
vis_sample->Set_Cur_Direction ((VisDirType)index);
Display_Point (vis_sample->Get_Camera_Transform ((VisDirType)index), false);
}
}
}
}
//
// Hilight the direction that is currently displayed
//
int direction = vis_sample->Get_Cur_Direction ();
int bit = (1 << direction);
m_AxisSel |= bit;
}
if (old_sel != m_AxisSel) {
//
// Repaint the axis area
//
HDC hdc = ::GetDC (m_hWnd);
Paint_Axis_Area (hdc);
::ReleaseDC (m_hWnd, hdc);
}
return found;
}
/////////////////////////////////////////////////////////////////////////////
//
// OnDestroy
//
/////////////////////////////////////////////////////////////////////////////
void
VisErrorReportDialogClass::OnDestroy (void)
{
CDialog::OnDestroy();
::RemoveProp (m_hWnd, "ALLOW_UPDATE");
return ;
}