summaryrefslogtreecommitdiff
path: root/hammer/anglebox.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /hammer/anglebox.cpp
downloadarchived-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.cpp562
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);
+ }
+ }
+}
+