diff options
| author | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
|---|---|---|
| committer | FluorescentCIAAfricanAmerican <[email protected]> | 2020-04-22 12:56:21 -0400 |
| commit | 3bf9df6b2785fa6d951086978a3e66f49427166a (patch) | |
| tree | 2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/anglebox.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/anglebox.cpp')
| -rw-r--r-- | hammer/anglebox.cpp | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/hammer/anglebox.cpp b/hammer/anglebox.cpp new file mode 100644 index 0000000..00e3d5e --- /dev/null +++ b/hammer/anglebox.cpp @@ -0,0 +1,562 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implements the angle custom control, a circle with a line indicating +// a rotation angle. +// +//=============================================================================// + +#include "stdafx.h" +#include "hammer.h" +#include "AngleBox.h" +#include "hammer_mathlib.h" +#include "CustomMessages.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include "tier0/memdbgon.h" + +#pragma warning(disable: 4244) + + +BEGIN_MESSAGE_MAP(CAngleBox, CWnd) + //{{AFX_MSG_MAP(CAngleBox) + ON_WM_MOUSEMOVE() + ON_WM_LBUTTONUP() + ON_WM_LBUTTONDOWN() + ON_WM_PAINT() + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. +//----------------------------------------------------------------------------- +CAngleBox::CAngleBox(void) +{ + m_vecAngles.Init(); + m_bDragging = false; + m_pEdit = NULL; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. +//----------------------------------------------------------------------------- +CAngleBox::~CAngleBox() +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nFlags - +// point - +//----------------------------------------------------------------------------- +void CAngleBox::OnMouseMove(UINT nFlags, CPoint point) +{ + if (m_bDragging) + { + // + // Remove old angle line by redrawing it (XOR). + // + DrawAngleLine(&m_DragDC); + + // + // Calculate new yaw. + // + int nNewYaw = fixang(180 - (int)lineangle(point.x, point.y, m_ptClientCenter.x, m_ptClientCenter.y)); + m_vecAngles.Init(); + m_vecAngles[YAW] = nNewYaw; + + // + // Draw the new angle line. + // + DrawAngleLine(&m_DragDC); + } + + CWnd::OnMouseMove(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nFlags - +// point - +//----------------------------------------------------------------------------- +void CAngleBox::OnLButtonUp(UINT nFlags, CPoint point) +{ + // release dc + if (m_bDragging) + { + ::ReleaseDC(m_hWnd, m_DragDC.Detach()); + m_bDragging = false; + ReleaseCapture(); + + // + // They've explicity set the angles, so clear the different flag for + // the multiselect case. + // + SetDifferent(false); + + GetParent()->PostMessage(ABN_CHANGED, GetDlgCtrlID(), 0); + } + + CWnd::OnLButtonUp(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nFlags - +// point - +//----------------------------------------------------------------------------- +void CAngleBox::OnLButtonDown(UINT nFlags, CPoint point) +{ + // + // Start dragging. + // + m_DragDC.Attach(::GetDC(m_hWnd)); + m_bDragging = true; + SetCapture(); + + CWnd::OnLButtonDown(nFlags, point); + + OnMouseMove(0, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pDC - +//----------------------------------------------------------------------------- +void CAngleBox::DrawAngleLine(CDC *pDC) +{ + if ((m_vecAngles[PITCH] != 0) || (m_vecAngles[ROLL] != 0) || + (m_vecAngles[YAW] < 0 || m_vecAngles[YAW] > 359) || m_bDifferent) + { + return; + } + + pDC->SetROP2(R2_XORPEN); + pDC->SelectStockObject(WHITE_PEN); + + CRect r; + GetClientRect(r); + m_ptClientCenter = r.CenterPoint(); + + double rad = r.Width() / 2 - 3; + + CPoint pt; + pt.x = m_ptClientCenter.x + sin(DEG2RAD((double)(m_vecAngles[YAW] + 90))) * rad + 0.5; + pt.y = m_ptClientCenter.y + cos(DEG2RAD((double)(m_vecAngles[YAW] + 90))) * rad + 0.5; + + pDC->MoveTo(m_ptClientCenter); + pDC->LineTo(pt); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the current state of the control as a keyvalue string. +// Input : szAngles - Buffer to receive angles string. +// Output : Returns 'szAngles'. +//----------------------------------------------------------------------------- +bool CAngleBox::GetAngles(QAngle &vecAngles) +{ + if (m_bDifferent) + { + return false; + } + + vecAngles = m_vecAngles; + + return(true); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns the current state of the control as a keyvalue string. +// Input : szAngles - Buffer to receive angles string. +// Output : Returns 'szAngles'. +//----------------------------------------------------------------------------- +char *CAngleBox::GetAngles(char *szAngles) +{ + QAngle vecAngles; + GetAngles(vecAngles); + sprintf(szAngles, "%g %g %g", (double)vecAngles[0], (double)vecAngles[1], (double)vecAngles[2]); + return(szAngles); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns a string indicating the current state of the angle control. +// This is used for setting the text in the companion edit control. +// Input : szBuf - Buffer to receive string. +//----------------------------------------------------------------------------- +char *CAngleBox::GetAngleEditText(char *szBuf) +{ + szBuf[0] = '\0'; + + if (m_bDifferent) + { + strcpy(szBuf, "(diff)"); + } + else if ((m_vecAngles[PITCH] == 90) && (m_vecAngles[YAW] == 0) && (m_vecAngles[ROLL] == 0)) + { + strcpy(szBuf, "Down"); + } + else if ((m_vecAngles[PITCH] == -90) && (m_vecAngles[YAW] == 0) && (m_vecAngles[ROLL] == 0)) + { + strcpy(szBuf, "Up"); + } + else if (m_vecAngles[YAW] >= 0) + { + itoa((int)m_vecAngles[YAW], szBuf, 10); + } + + return(szBuf); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called internally and by the linked combo box, this updates the angles +// without updating the linked combo box. +// Input : szAngles - +// bRedraw - +//----------------------------------------------------------------------------- +void CAngleBox::SetAnglesInternal(const QAngle &vecAngles, bool bRedraw) +{ + QAngle vecAngleSet = vecAngles; + while (vecAngleSet[YAW] < 0) + { + vecAngleSet[YAW] += 360.0; + } + + CDC *pDC = NULL; + + if (bRedraw) + { + // + // Erase the old line. + // + Assert(::IsWindow(m_hWnd)); + pDC = GetDC(); + if (pDC != NULL) + { + DrawAngleLine(pDC); + } + } + + // + // Update the data member. + // + m_vecAngles = vecAngleSet; + + if ((bRedraw) && (pDC != NULL)) + { + // + // Draw the new line. + // + DrawAngleLine(pDC); + ReleaseDC(pDC); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Called from the client code, this sets our angles and updates the +// linked combo box. +// Input : szAngles - +// bRedraw - +//----------------------------------------------------------------------------- +void CAngleBox::SetAngles(const QAngle &vecAngles, bool bRedraw) +{ + SetAnglesInternal(vecAngles, bRedraw); + UpdateAngleEditText(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called from the client code, this sets our angles via a string and +// updates the linked combo box. +// Input : szAngles - +// bRedraw - +//----------------------------------------------------------------------------- +void CAngleBox::SetAngles(const char *szAngles, bool bRedraw) +{ + QAngle vecAngles(0, 0, 0); + sscanf(szAngles, "%f %f %f", &vecAngles[PITCH], &vecAngles[YAW], &vecAngles[ROLL]); + SetAngles(vecAngles, bRedraw); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called internally and by the linked combo box, this sets our +// 'different' state without updating the linked combo box. +// Input : bDifferent - +// bRedraw - +//----------------------------------------------------------------------------- +void CAngleBox::SetDifferentInternal(bool bDifferent, bool bRedraw) +{ + CDC *pDC = NULL; + + if (bRedraw) + { + // + // Erase the old line. + // + Assert(::IsWindow(m_hWnd)); + pDC = GetDC(); + if (pDC != NULL) + { + DrawAngleLine(pDC); + } + } + + // + // Update the data member. + // + m_bDifferent = bDifferent; + + if ((bRedraw) && (pDC != NULL)) + { + // + // Draw the new line. + // + DrawAngleLine(pDC); + ReleaseDC(pDC); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets our state to indicate multiselect of objects with different +// angles to avoid mucking with the angles unless they explicitly set +// them to something new. +//----------------------------------------------------------------------------- +void CAngleBox::SetDifferent(bool bDifferent, bool bRedraw) +{ + SetDifferentInternal(bDifferent, bRedraw); + UpdateAngleEditText(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CAngleBox::OnPaint(void) +{ + PAINTSTRUCT ps; + CDC *pDC = BeginPaint(&ps); + + if (pDC == NULL) + { + return; + } + + CBrush brushWindow(GetSysColor(COLOR_3DFACE)); + CBrush brushBlack(RGB(0, 0, 0)); + + CBrush *pBackBrush = IsWindowEnabled() ? &brushBlack : &brushWindow; + + CRect r; + GetClientRect(r); + + // + // Fill with the window color. + // + pDC->FillRect(&r, &brushWindow); + + // + // Draw a 3D circle. + // + m_ptClientCenter = r.CenterPoint(); + + pDC->SelectStockObject(NULL_PEN); + pDC->SelectObject(pBackBrush); + pDC->Ellipse(r); + + CPen hi(PS_SOLID, 2, GetSysColor(COLOR_3DSHADOW)); + CPen lo(PS_SOLID, 2, GetSysColor(COLOR_3DHILIGHT)); + + pDC->SelectObject(hi); + pDC->Arc(r, CPoint(r.right, r.top), CPoint(r.left, r.bottom)); + pDC->SelectObject(lo); + pDC->Arc(r, CPoint(r.left, r.bottom), CPoint(r.right, r.top)); + + // + // Draw center point. + // + pDC->SetPixel(m_ptClientCenter, RGB(0xff, 0xff, 0xff)); + + // + // Draw line indicating angles direction. + // + if (IsWindowEnabled()) + { + DrawAngleLine(pDC); + } + + EndPaint(&ps); +} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables the angles controls. +//----------------------------------------------------------------------------- +void CAngleBox::Enable(bool bEnable) +{ + if (bEnable) + { + EnableWindow(TRUE); + + if (m_pEdit) + { + m_pEdit->EnableWindow(TRUE); + } + } + else + { + EnableWindow(FALSE); + + if (m_pEdit) + { + m_pEdit->EnableWindow(FALSE); + } + } + + Invalidate(FALSE); + UpdateWindow(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Hides or shows the angles controls. +//----------------------------------------------------------------------------- +void CAngleBox::Show(bool bShow) +{ + if (bShow) + { + ShowWindow(SW_SHOW); + + if (m_pEdit) + { + m_pEdit->ShowWindow(SW_SHOW); + } + } + else + { + ShowWindow(SW_HIDE); + + if (m_pEdit) + { + m_pEdit->ShowWindow(SW_HIDE); + } + } + + Invalidate(FALSE); + UpdateWindow(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Updates the text in the angle combo to reflect the current angles +// in the angles control. +//----------------------------------------------------------------------------- +void CAngleBox::UpdateAngleEditText(void) +{ + if (m_pEdit) + { + char szBuf[20]; + GetAngleEditText(szBuf); + m_pEdit->SetAnglesInternal(szBuf); + } +} + + +BEGIN_MESSAGE_MAP(CAngleCombo, CWnd) + //{{AFX_MSG_MAP(CAngleBox) + ON_CONTROL_REFLECT(CBN_EDITCHANGE, OnChangeAngleEdit) + ON_CONTROL_REFLECT(CBN_SELENDOK, OnSelChangeAngleEdit) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +//----------------------------------------------------------------------------- +// Purpose: Construktor. +//----------------------------------------------------------------------------- +CAngleCombo::CAngleCombo() + : CComboBox() +{ + m_pBox = NULL; + m_bEnableUpdate = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *szAngles - +//----------------------------------------------------------------------------- +void CAngleCombo::SetAnglesInternal(const char *szAngles) +{ + m_bEnableUpdate = false; + SetWindowText(szAngles); + m_bEnableUpdate = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles a change in the contents of the angle edit control. +//----------------------------------------------------------------------------- +void CAngleCombo::OnChangeAngleEdit(void) +{ + if (m_bEnableUpdate) + { + char buf[64]; + GetWindowText(buf, 64); + UpdateAngleBox(buf); + + GetParent()->PostMessage(ABN_CHANGED, GetDlgCtrlID(), 0); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles a change in the current selection of the angle edit combo. +//----------------------------------------------------------------------------- +void CAngleCombo::OnSelChangeAngleEdit(void) +{ + char buf[64]; + int nSel = GetCurSel(); + GetLBText(nSel, buf); + UpdateAngleBox(buf); + + GetParent()->PostMessage(ABN_CHANGED, GetDlgCtrlID(), 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: Updates angle box with the settings from the combo box. Call the +// internal functions so we don't get a reflected notification, mucking +// up our state. +//----------------------------------------------------------------------------- +void CAngleCombo::UpdateAngleBox(char *szText) +{ + if (m_pBox) + { + m_pBox->SetDifferentInternal(false); + + if (V_isdigit(szText[0])) + { + QAngle vecAngles(0, atoi(szText), 0); + m_pBox->SetAnglesInternal(vecAngles, true); + } + else if (!stricmp(szText, "down")) + { + m_pBox->SetAnglesInternal(QAngle(90, 0, 0), true); + } + else + { + m_pBox->SetAnglesInternal(QAngle(-90, 0, 0), true); + } + } +} + |