//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============// // // Purpose: Handles the selection of faces and material application. // // TODO: consider making face selection a mode of the selection tool // // $NoKeywords: $ //=============================================================================// #include "stdafx.h" #include "FaceEditSheet.h" #include "History.h" #include "MainFrm.h" #include "MapDoc.h" #include "MapSolid.h" #include "MapView2D.h" #include "MapView3D.h" #include "StatusBarIDs.h" #include "ToolManager.h" #include "ToolMaterial.h" #include "Options.h" // memdbgon must be the last include file in a .cpp file!!! #include //----------------------------------------------------------------------------- // Purpose: Called when this tool is deactivated in favor of another tool. // Input : eNewTool - The tool that is being activated. //----------------------------------------------------------------------------- void CToolMaterial::OnDeactivate() { if ( m_pDocument->GetTools()->GetActiveToolID() != TOOL_FACEEDIT_DISP ) { // Clear the selected faces when we are deactivated. m_pDocument->SelectFace(NULL, 0, scClear ); } } //----------------------------------------------------------------------------- // Purpose: // Input : pView - // nFlags - // point - // Output : Returns true if the message was handled, false if not. //----------------------------------------------------------------------------- bool CToolMaterial::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) { if (nFlags & MK_CONTROL) { // // CONTROL is down, perform selection only. // pView->SelectAt( vPoint, false, true); } else { pView->SelectAt( vPoint, true, true); } return (true); } //----------------------------------------------------------------------------- // Purpose: Handles left mouse button down events in the 3D view. // Input : Per CWnd::OnLButtonDown. // Output : Returns true if the message was handled, false if not. //----------------------------------------------------------------------------- bool CToolMaterial::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) { CMapDoc *pDoc = pView->GetMapDoc(); if (pDoc == NULL) { return false; } bool bShift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0); ULONG ulFace; CMapClass *pObject = pView->NearestObjectAt( vPoint, ulFace); if ((pObject != NULL) && (pObject->IsMapClass(MAPCLASS_TYPE(CMapSolid)))) { CMapSolid *pSolid = (CMapSolid *)pObject; int cmd = scToggle | scClear; // No clear if CTRL pressed. if (GetAsyncKeyState(VK_CONTROL) & 0x8000) { cmd &= ~scClear; } // If they are holding down SHIFT, select the entire solid. if (bShift) { pDoc->SelectFace(pSolid, -1, cmd); } // Otherwise, select a single face. else { pDoc->SelectFace(pSolid, ulFace, cmd); } } return true; } //----------------------------------------------------------------------------- // Purpose: Handles right mouse button down events in the 3D view. // Input : Per CWnd::OnRButtonDown. // Output : Returns true if the message was handled, false if not. //----------------------------------------------------------------------------- bool CToolMaterial::OnRMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) { BOOL bShift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0); BOOL bEdgeAlign = ((GetAsyncKeyState(VK_MENU) & 0x8000) != 0); ULONG ulFace; CMapClass *pObject = pView->NearestObjectAt( vPoint, ulFace); if (pObject != NULL) { if (pObject->IsMapClass(MAPCLASS_TYPE(CMapSolid))) { CMapSolid *pSolid = (CMapSolid *)pObject; GetHistory()->MarkUndoPosition(NULL, "Apply texture"); GetHistory()->Keep(pSolid); // Setup the flags. int cmdFlags = 0; if (bEdgeAlign) { cmdFlags |= CFaceEditSheet::cfEdgeAlign; } // If we're in a lightmap grid preview window, only apply the lightmap scale. int eMode; if (pView->GetDrawType() == VIEW3D_LIGHTMAP_GRID) { eMode = CFaceEditSheet::ModeApplyLightmapScale; } else { eMode = CFaceEditSheet::ModeApplyAll; } // If they are holding down the shift key, apply to the entire solid. if (bShift) { int nFaces = pSolid->GetFaceCount(); for(int i = 0; i < nFaces; i++) { GetMainWnd()->m_pFaceEditSheet->ClickFace(pSolid, i, cmdFlags, eMode); } } // If not, apply to a single face. else { GetMainWnd()->m_pFaceEditSheet->ClickFace(pSolid, ulFace, cmdFlags, eMode); } } } return true; } //----------------------------------------------------------------------------- // Purpose: Handles the mouse move message in the 3D view. // Input : Per CWnd::OnMouseMove. //----------------------------------------------------------------------------- bool CToolMaterial::OnMouseMove3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) { // // Manage the cursor. // static HCURSOR hcurFacePaint = 0; if (!hcurFacePaint) { hcurFacePaint = LoadCursor(AfxGetInstanceHandle(), MAKEINTRESOURCE(IDC_FACEPAINT)); } SetCursor(hcurFacePaint); return true; } //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- void CToolMaterial::UpdateStatusBar() { CString str; str.Format("%d faces selected", GetMainWnd()->m_pFaceEditSheet->GetFaceListCount() ); SetStatusText(SBI_SELECTION, str); SetStatusText(SBI_SIZE, ""); } //----------------------------------------------------------------------------- // Purpose: Handles the key down event in the 3D view. // Input : Per CWnd::OnKeyDown. // Output : Returns true if the message was handled, false if not. //----------------------------------------------------------------------------- bool CToolMaterial::OnKeyDown3D( CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags ) { // TO DO: undo? // justify (SHIFT?) CMapDoc *pDoc = pView->GetMapDoc(); if ( pDoc == NULL ) { return false; } if ( nChar == VK_UP || nChar == VK_DOWN || nChar == VK_LEFT || nChar == VK_RIGHT ) { // Bail out if the user doesn't have Nudging enabled. if ( !Options.view2d.bNudge ) { return false; } CFaceEditSheet *pSheet = GetMainWnd()->m_pFaceEditSheet; if( pSheet ) { // Check for a face list. int nFaceCount = pSheet->GetFaceListCount(); if( nFaceCount == 0 ) { return false; } int nGridSize = m_pDocument->GetGridSpacing(); bool bCtrlDown = ( ( GetAsyncKeyState( VK_CONTROL ) & 0x8000 ) != 0 ); if ( bCtrlDown ) { nGridSize = 1; } for( int ndxface = 0; ndxface < nFaceCount; ndxface++ ) { CMapFace *pFace; pFace = pSheet->GetFaceListDataFace( ndxface ); TEXTURE &t = pFace->texture; if ( nChar == VK_UP ) { t.VAxis[ 3 ] = ( (int)( t.VAxis[ 3 ] + nGridSize ) % 1024 ); } else if ( nChar == VK_DOWN ) { t.VAxis[ 3 ] = ( (int)( t.VAxis[ 3 ] - nGridSize ) % 1024 ); } else if ( nChar == VK_LEFT ) { t.UAxis[ 3 ] = ( (int)( t.UAxis[ 3 ] + nGridSize ) % 1024 ); } else { t.UAxis[ 3 ] = ( (int)( t.UAxis[ 3 ] - nGridSize ) % 1024 ); } pFace->CalcTextureCoords(); pSheet->m_MaterialPage.UpdateDialogData( pFace ); } pDoc->SetModifiedFlag(); return true; } } return false; }