diff options
Diffstat (limited to 'hammer/toolpickface.cpp')
| -rw-r--r-- | hammer/toolpickface.cpp | 483 |
1 files changed, 483 insertions, 0 deletions
diff --git a/hammer/toolpickface.cpp b/hammer/toolpickface.cpp new file mode 100644 index 0000000..2599e48 --- /dev/null +++ b/hammer/toolpickface.cpp @@ -0,0 +1,483 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Tool used for picking brush faces. +// +// Left click - single select face +// +Ctrl - multiselect a single face +// +Shift - all faces on the brush +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "MapFace.h" +#include "resource.h" +#include "ToolPickFace.h" +#include "MapSolid.h" +#include "MapView3D.h" +#include "mapdoc.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. Inits data members. +//----------------------------------------------------------------------------- +CToolPickFace::CToolPickFace(void) +{ + m_pNotifyTarget = NULL; + m_bAllowMultiSelect = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. +//----------------------------------------------------------------------------- +CToolPickFace::~CToolPickFace(void) +{ +} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables multiselect for this tool. +//----------------------------------------------------------------------------- +void CToolPickFace::AllowMultiSelect(bool bAllow) +{ + m_bAllowMultiSelect = bAllow; + + // + // Shouldn't ever happen, but you never know. + // + if ((!bAllow) && (m_Faces.Count() > 1)) + { + CMapFace *pFace = m_Faces[0].pFace; + DeselectAll(); + SelectFace(pFace); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Called when the tool is deactivated. +// Input : eNewTool - The ID of the tool that is being activated. +//----------------------------------------------------------------------------- +void CToolPickFace::OnDeactivate() +{ + DeselectAll(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button up message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnLMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button up message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + bool bControl = ((nFlags & MK_CONTROL) != 0); + bool bShift = ((nFlags & MK_SHIFT) != 0); + + if (!m_bAllowMultiSelect) + { + // Ignore shift click for single selection mode. + bShift = false; + } + + unsigned long uFace; + CMapClass *pObject = pView->NearestObjectAt( vPoint, uFace); + if (pObject != NULL) + { + CMapSolid *pSolid = dynamic_cast <CMapSolid *>(pObject); + if (pSolid != NULL) + { + // + // We clicked on a solid. + // + if (!bShift) + { + // + // Get the face that we clicked on. + // + CMapFace *pFace = pSolid->GetFace(uFace); + Assert(pFace != NULL); + + if (pFace != NULL) + { + if ((!m_bAllowMultiSelect) || (!bControl)) + { + // Single select. + DeselectAll(); + SelectFace(pFace); + } + else + { + // Multiselect. + CycleSelectFace(pFace); + } + } + } + else + { + // + // Holding down shift. Select or deselect all the faces on the solid. + // Only deselect if all the faces in the solid were selected. + // + bool bAllSelected = true; + int nFaceCount = pSolid->GetFaceCount(); + for (int nFace = 0; nFace < nFaceCount; nFace++) + { + CMapFace *pFace = pSolid->GetFace(nFace); + int nIndex = FindFace(pFace); + if ((nIndex == -1) || (m_Faces[nIndex].eState != FaceState_Select)) + { + bAllSelected = false; + break; + } + } + + if (!bControl) + { + DeselectAll(); + } + + nFaceCount = pSolid->GetFaceCount(); + for (int nFace = 0; nFace < nFaceCount; nFace++) + { + CMapFace *pFace = pSolid->GetFace(nFace); + if (bAllSelected) + { + DeselectFace(pFace); + } + else + { + SelectFace(pFace); + } + } + } + + if (m_pNotifyTarget) + { + m_pNotifyTarget->OnNotifyPickFace(this); + } + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button double click message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnLMouseDblClk3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the right mouse button up message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnRMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the mouse button up message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnRMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the mouse move message in the 3D view. +// Input : pView - The view that the event occurred in. +// nFlags - Flags per the Windows mouse message. +// point - Point in client coordinates where the event occurred. +// Output : Returns true if the message was handled by the tool, false if not. +//----------------------------------------------------------------------------- +bool CToolPickFace::OnMouseMove3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + SetEyedropperCursor(); + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the cursor to the eyedropper cursor. +//----------------------------------------------------------------------------- +void CToolPickFace::SetEyedropperCursor(void) +{ + static HCURSOR hcurEyedropper = NULL; + + if (!hcurEyedropper) + { + hcurEyedropper = LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_EYEDROPPER)); + } + + SetCursor(hcurEyedropper); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pFace - +//----------------------------------------------------------------------------- +void CToolPickFace::CycleSelectFace(CMapFace *pFace) +{ + int nIndex = FindFace(pFace); + if (nIndex != -1) + { + // + // The face is in our list, update its selection state. + // + if (m_Faces[nIndex].eState == FaceState_Partial) + { + DeselectFace(nIndex); + } + else if (m_Faces[nIndex].eState == FaceState_Select) + { + if (m_Faces[nIndex].eOriginalState == FaceState_Partial) + { + m_Faces[nIndex].eState = FaceState_Partial; + pFace->SetSelectionState(SELECT_MULTI_PARTIAL); + } + else + { + DeselectFace(nIndex); + } + } + else if (m_Faces[nIndex].eState == FaceState_None) + { + m_Faces[nIndex].eState = FaceState_Select; + pFace->SetSelectionState(SELECT_NORMAL); + } + } + else + { + // + // The face is not in our list, add it. + // + AddToList(pFace, FaceState_Select); + pFace->SetSelectionState(SELECT_NORMAL); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the fully selected and partially selected faces for the picker. +// Input : FaceListFull - +// FaceListPartial - +//----------------------------------------------------------------------------- +void CToolPickFace::SetSelectedFaces(CMapFaceList &FaceListFull, CMapFaceList &FaceListPartial) +{ + m_Faces.RemoveAll(); + + for (int i = 0; i < FaceListFull.Count(); i++) + { + CMapFace *pFace = FaceListFull.Element(i); + + AddToList(pFace, FaceState_Select); + pFace->SetSelectionState(SELECT_NORMAL); + } + + for (int i = 0; i < FaceListPartial.Count(); i++) + { + CMapFace *pFace = FaceListPartial.Element(i); + + AddToList(pFace, FaceState_Partial); + pFace->SetSelectionState(SELECT_MULTI_PARTIAL); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pFace - +//----------------------------------------------------------------------------- +int CToolPickFace::FindFace(CMapFace *pFace) +{ + for (int i = 0; i < m_Faces.Count(); i++) + { + if (m_Faces[i].pFace == pFace) + { + return i; + } + } + + return -1; +} + + +//----------------------------------------------------------------------------- +// Purpose: Clears the selection set. +//----------------------------------------------------------------------------- +void CToolPickFace::DeselectAll(void) +{ + for (int i = 0; i < m_Faces.Count(); i++) + { + m_Faces[i].pFace->SetSelectionState(SELECT_NONE); + } + + m_Faces.RemoveAll(); + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Selects the face unconditionally. +// Input : pFace - face to select. +//----------------------------------------------------------------------------- +void CToolPickFace::SelectFace(CMapFace *pFace) +{ + int nIndex = FindFace(pFace); + if (nIndex != -1) + { + // + // The face is in our list, update its selection state. + // + m_Faces[nIndex].eState = FaceState_Select; + pFace->SetSelectionState(SELECT_NORMAL); + } + else + { + // + // The face is not in our list, add it. + // + AddToList(pFace, FaceState_Select); + pFace->SetSelectionState(SELECT_NORMAL); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Deselects the given face. +//----------------------------------------------------------------------------- +void CToolPickFace::DeselectFace(CMapFace *pFace) +{ + int nIndex = FindFace(pFace); + if (nIndex != -1) + { + DeselectFace(nIndex); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Removes the face at the given index from the selection set. +// Input : nIndex - Index of the face in the selection list. +//----------------------------------------------------------------------------- +void CToolPickFace::DeselectFace(int nIndex) +{ + Assert(m_Faces.IsValidIndex(nIndex)); + + if (m_Faces.IsValidIndex(nIndex)) + { + if (m_Faces[nIndex].eOriginalState != FaceState_Partial) + { + m_Faces[nIndex].pFace->SetSelectionState(SELECT_NONE); + + // + // Remove the face from our list. + // + RemoveFromList(nIndex); + } + else + { + // + // Just set the state to deselected so we can cycle back to partial selection. + // + m_Faces[nIndex].pFace->SetSelectionState(SELECT_NONE); + m_Faces[nIndex].eState = FaceState_None; + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pFace - +// eState - +//----------------------------------------------------------------------------- +void CToolPickFace::AddToList(CMapFace *pFace, FaceState_t eState) +{ + int nIndex = m_Faces.AddToTail(); + m_Faces[nIndex].pFace = pFace; + m_Faces[nIndex].eState = eState; + m_Faces[nIndex].eOriginalState = eState; + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D ); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nIndex - +//----------------------------------------------------------------------------- +void CToolPickFace::RemoveFromList(int nIndex) +{ + Assert(m_Faces.IsValidIndex(nIndex)); + + if (m_Faces.IsValidIndex(nIndex)) + { + m_Faces.FastRemove(nIndex); + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_ONLY_3D ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns lists of fully selected and partially selected faces. +//----------------------------------------------------------------------------- +void CToolPickFace::GetSelectedFaces(CMapFaceList &FaceListFull, CMapFaceList &FaceListPartial) +{ + FaceListFull.RemoveAll(); + FaceListPartial.RemoveAll(); + + for (int i = 0; i < m_Faces.Count(); i++) + { + if (m_Faces[i].eState == FaceState_Select) + { + FaceListFull.AddToTail(m_Faces[i].pFace); + } + else if (m_Faces[i].eState == FaceState_Partial) + { + FaceListPartial.AddToTail(m_Faces[i].pFace); + } + } +} + |