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/ToolCamera.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/ToolCamera.cpp')
| -rw-r--r-- | hammer/ToolCamera.cpp | 816 |
1 files changed, 816 insertions, 0 deletions
diff --git a/hammer/ToolCamera.cpp b/hammer/ToolCamera.cpp new file mode 100644 index 0000000..ee54d2d --- /dev/null +++ b/hammer/ToolCamera.cpp @@ -0,0 +1,816 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: +// +// $NoKeywords: $ +//=============================================================================// + +#include "stdafx.h" +#include "ToolCamera.h" +#include "SaveInfo.h" +#include "MainFrm.h" // dvs: remove? +#include "MapDefs.h" +#include "MapDoc.h" +#include "MapView2D.h" +#include "MapView3D.h" +#include "Options.h" +#include "Render2D.h" +#include "StatusBarIDs.h" // dvs: remove +#include "ToolManager.h" +#include "hammer_mathlib.h" +#include "vgui/Cursor.h" +#include "Selection.h" + +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +#pragma warning(disable:4244) + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +Camera3D::Camera3D(void) +{ + Cameras.EnsureCapacity(16); + SetEmpty(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Returns true if we are dragging a camera, false if not. // dvs: rename +//----------------------------------------------------------------------------- +bool Camera3D::IsEmpty(void) +{ + return (Cameras.Count() == 0); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Camera3D::SetEmpty(void) +{ + Cameras.RemoveAll(); + m_iActiveCamera = -1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pt - +// BOOL - +// Output : int +//----------------------------------------------------------------------------- +int Camera3D::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles) +{ + for(int i = 0; i < Cameras.Count(); i++) + { + for ( int j=0; j<2; j++ ) + { + if( HitRect( pView, ptClient, Cameras[i].position[j], HANDLE_RADIUS ) ) + { + return MAKELONG(i+1, j); + } + } + } + + return FALSE; +} + +//----------------------------------------------------------------------------- +// Purpose: Get rid of extra cameras if we have too many. +//----------------------------------------------------------------------------- +void Camera3D::EnsureMaxCameras() +{ + int nMax = max( Options.general.nMaxCameras, 1 ); + + int nToRemove = Cameras.Count() - nMax; + if ( nToRemove > 0 ) + { + m_iActiveCamera = max( m_iActiveCamera - nToRemove, 0 ); + + while ( nToRemove-- ) + Cameras.Remove( 0 ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bSave - +//----------------------------------------------------------------------------- +void Camera3D::FinishTranslation(bool bSave) +{ + if (bSave) + { + if ( m_iActiveCamera == Cameras.Count() ) + { + Cameras.AddToTail(); + EnsureMaxCameras(); + } + + Cameras[m_iActiveCamera] = m_MoveCamera; + } + + Tool3D::FinishTranslation(bSave); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pt - +// uFlags - +// CSize& - +// Output : Returns TRUE on success, FALSE on failure. +//----------------------------------------------------------------------------- +bool Camera3D::UpdateTranslation(const Vector &vUpdate, UINT uFlags) +{ + Vector vCamDelta = m_MoveCamera.position[1] - m_MoveCamera.position[0]; + + Vector vNewPos = m_vOrgPos + vUpdate; + + // snap point if need be + if ( uFlags & constrainSnap ) + m_pDocument->Snap( vNewPos, uFlags ); + + m_MoveCamera.position[m_nMovePositionIndex] = vNewPos; + + if(uFlags & constrainMoveAll) + { + m_MoveCamera.position[(m_nMovePositionIndex+1)%2] = vNewPos + vCamDelta; + } + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pCamPos - +// iCamera - +//----------------------------------------------------------------------------- +void Camera3D::GetCameraPos(Vector &vViewPos, Vector &vLookAt) +{ + if(!inrange(m_iActiveCamera, 0, Cameras.Count())) + { + vViewPos.Init(); + vLookAt.Init(); + return; + } + + vViewPos = Cameras[m_iActiveCamera].position[0]; + vLookAt = Cameras[m_iActiveCamera].position[1]; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pCamPos - +// iCamera - +//----------------------------------------------------------------------------- +void Camera3D::AddCamera(CAMSTRUCT &camera) +{ + Cameras.AddToTail( camera ); + EnsureMaxCameras(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pRender - +//----------------------------------------------------------------------------- +void Camera3D::RenderTool2D(CRender2D *pRender) +{ + for (int i = 0; i < Cameras.Count(); i++) + { + CAMSTRUCT *pDrawCam = &Cameras[i]; + + if (IsTranslating() && (i == m_iActiveCamera)) + { + pDrawCam = &m_MoveCamera; + } + + // + // Draw the line between. + // + if (i == m_iActiveCamera) + { + pRender->SetDrawColor( 255, 0, 0 ); + } + else + { + pRender->SetDrawColor( 0, 255, 255 ); + } + + pRender->DrawLine( pDrawCam->position[MovePos], pDrawCam->position[MoveLook] ); + + // + // Draw camera handle. + // + pRender->SetHandleStyle(HANDLE_RADIUS, CRender::HANDLE_CIRCLE ); + pRender->SetHandleColor( 0, 255, 255 ); + pRender->DrawHandle( pDrawCam->position[MovePos] ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles key values being read from the MAP file. +// Input : szKey - Key being loaded. +// szValue - Value of the key being loaded. +// pCam - Camera structure to place the values into. +// Output : Returns ChunkFile_Ok to indicate success. +//----------------------------------------------------------------------------- +ChunkFileResult_t Camera3D::LoadCameraKeyCallback(const char *szKey, const char *szValue, CAMSTRUCT *pCam) +{ + if (!stricmp(szKey, "look")) + { + CChunkFile::ReadKeyValueVector3(szValue, pCam->position[MoveLook]); + } + else if (!stricmp(szKey, "position")) + { + CChunkFile::ReadKeyValueVector3(szValue, pCam->position[MovePos]); + } + + return(ChunkFile_Ok); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles key values being read from the MAP file. +// Input : szKey - Key being loaded. +// szValue - Value of the key being loaded. +// pCam - Camera structure to place the values into. +// Output : Returns ChunkFile_Ok to indicate success. +//----------------------------------------------------------------------------- +ChunkFileResult_t Camera3D::LoadCamerasKeyCallback(const char *szKey, const char *szValue, Camera3D *pCameras) +{ + if (!stricmp(szKey, "activecamera")) + { + pCameras->m_iActiveCamera = atoi(szValue); + } + + return(ChunkFile_Ok); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pLoadInfo - +// *pSolid - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t Camera3D::LoadCameraCallback(CChunkFile *pFile, Camera3D *pCameras) +{ + CAMSTRUCT Cam; + memset(&Cam, 0, sizeof(Cam)); + + ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadCameraKeyCallback, &Cam); + + if (eResult == ChunkFile_Ok) + { + pCameras->AddCamera( Cam ); + } + + return(eResult); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFile - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t Camera3D::LoadVMF(CChunkFile *pFile) +{ + // + // Set up handlers for the subchunks that we are interested in. + // + CChunkHandlerMap Handlers; + Handlers.AddHandler("camera", (ChunkHandler_t)LoadCameraCallback, this); + + pFile->PushHandlers(&Handlers); + ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadCamerasKeyCallback, this); + pFile->PopHandlers(); + + if (eResult == ChunkFile_Ok) + { + // + // Make sure the active camera is legal. + // + if (Cameras.Count() == 0) + { + m_iActiveCamera = -1; + } + else if (!inrange(m_iActiveCamera, 0, Cameras.Count())) + { + m_iActiveCamera = 0; + } + } + + return(eResult); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : &dir - +// &pos - +//----------------------------------------------------------------------------- +void Camera3D::UpdateActiveCamera(Vector &vViewPos, Vector &vDir) +{ + if(!inrange(m_iActiveCamera, 0, Cameras.Count())) + return; + + Vector& camPos = Cameras[m_iActiveCamera].position[MovePos]; + Vector& lookPos = Cameras[m_iActiveCamera].position[MoveLook]; + + // get current length + Vector delta; + for(int i = 0; i < 3; i++) + delta[i] = camPos[i] - lookPos[i]; + + float length = VectorLength(delta); + + if ( length < 1 ) + length = 1; + + camPos = vViewPos; + + for(int i = 0; i < 3; i++) + lookPos[i] = camPos[i] + vDir[i] * length; + + if ( IsActiveTool() ) + { + if (Options.view2d.bCenteroncamera) + { + VIEW2DINFO vi; + vi.wFlags = VI_CENTER; + vi.ptCenter = vViewPos; + m_pDocument->SetView2dInfo(vi); + } + + m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : type - +//----------------------------------------------------------------------------- +void Camera3D::SetNextCamera(SNCTYPE type) +{ + if(Cameras.Count()==0) + { + m_iActiveCamera = -1; + return; + } + + switch(type) + { + case sncNext: + ++m_iActiveCamera; + if(m_iActiveCamera >= Cameras.Count() ) + m_iActiveCamera = 0; + break; + case sncPrev: + --m_iActiveCamera; + if(m_iActiveCamera < 0) + m_iActiveCamera = Cameras.Count()-1; + break; + case sncFirst: + m_iActiveCamera = 0; + break; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void Camera3D::DeleteActiveCamera() +{ + if(!inrange(m_iActiveCamera, 0, Cameras.Count())) + return; + + Cameras.Remove(m_iActiveCamera); + + if(m_iActiveCamera >= Cameras.Count() ) + m_iActiveCamera = Cameras.Count()-1; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : file - +// fIsStoring - +//----------------------------------------------------------------------------- +void Camera3D::SerializeRMF(std::fstream& file, BOOL fIsStoring) +{ + float fVersion = 0.2f, fThisVersion; + + int nCameras = Cameras.Count(); + + if(fIsStoring) + { + file.write((char*)&fVersion, sizeof(fVersion) ); + + file.write((char*)&m_iActiveCamera, sizeof(m_iActiveCamera) ); + file.write((char*)&nCameras, sizeof(nCameras)); + for(int i = 0; i < nCameras; i++) + { + file.write((char*)&Cameras[i], sizeof(CAMSTRUCT)); + } + } + else + { + file.read((char*)&fThisVersion, sizeof(fThisVersion) ); + + if(fThisVersion >= 0.2f) + { + file.read((char*)&m_iActiveCamera, sizeof(m_iActiveCamera)); + } + + file.read((char*)&nCameras, sizeof (nCameras) ); + + Cameras.RemoveAll(); + Cameras.EnsureCapacity(nCameras); + + for(int i = 0; i < nCameras; i++) + { + CAMSTRUCT cam; + file.read((char*)&cam, sizeof(CAMSTRUCT)); + Cameras.AddToTail( cam ); + } + EnsureMaxCameras(); + + Assert( Cameras.Count() == nCameras ); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pFile - +// Output : ChunkFileResult_t +//----------------------------------------------------------------------------- +ChunkFileResult_t Camera3D::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo) +{ + ChunkFileResult_t eResult = pFile->BeginChunk( GetVMFChunkName() ); + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueInt("activecamera", m_iActiveCamera); + } + + if (eResult == ChunkFile_Ok) + { + for (int i = 0; i < Cameras.Count(); i++) + { + eResult = pFile->BeginChunk("camera"); + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueVector3("position", Cameras[i].position[MovePos]); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->WriteKeyValueVector3("look", Cameras[i].position[MoveLook]); + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->EndChunk(); + } + + if (eResult != ChunkFile_Ok) + { + break; + } + } + } + + if (eResult == ChunkFile_Ok) + { + eResult = pFile->EndChunk(); + } + + return(eResult); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the key down event in the 2D view. +// Input : Per CWnd::OnKeyDown. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnKeyDown2D(CMapView2D *pView, UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if (nChar == VK_DELETE || nChar == VK_NEXT || nChar == VK_PRIOR) + { + CMapDoc *pDoc = pView->GetMapDoc(); + + if (nChar == VK_DELETE) + { + DeleteActiveCamera(); + } + else if (nChar == VK_NEXT) + { + SetNextCamera(Camera3D::sncNext); + } + else + { + SetNextCamera(Camera3D::sncPrev); + } + + Vector viewPos,lookAt; + + GetCameraPos( viewPos, lookAt ); + pDoc->UpdateAllCameras( &viewPos, &lookAt, NULL ); + + return true; + } + else if (nChar == VK_ESCAPE) + { + OnEscape(); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button down event in the 2D view. +// Input : Per CWnd::OnLButtonDown. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) +{ + CMapDoc *pDoc = pView->GetMapDoc(); + + pView->SetCapture(); + + // + // If there are no cameras created yet or they are holding down + // the SHIFT key, create a new camera now. + // + + Vector vecWorld; + pView->ClientToWorld( vecWorld, vPoint ); + + if ( IsEmpty() || (nFlags & MK_SHIFT)) + { + // + // Build a point in world space to place the new camera. + // + + if ( !pDoc->GetSelection()->IsEmpty() ) + { + Vector vecCenter; + pDoc->GetSelection()->GetBoundsCenter(vecCenter); + vecWorld[pView->axThird] = vecCenter[pView->axThird]; + } + else + { + vecWorld[pView->axThird] = COORD_NOTINIT; + pDoc->GetBestVisiblePoint(vecWorld); + } + + // + // Create a new camera. + // + m_vOrgPos = vecWorld; + m_MoveCamera.position[MovePos] = vecWorld; + m_MoveCamera.position[MoveLook] = vecWorld; + m_nMovePositionIndex = MoveLook; + + // set as active camera + m_iActiveCamera = Cameras.AddToTail(m_MoveCamera);; + EnsureMaxCameras(); + + StartTranslation(pView, vPoint ); + } + // + // Otherwise, try to drag an existing camera handle. + // + else + { + int dwHit = HitTest( pView, vPoint ); + + if ( dwHit ) + { + m_iActiveCamera = LOWORD(dwHit)-1; + m_MoveCamera = Cameras[m_iActiveCamera]; + m_nMovePositionIndex = HIWORD(dwHit); + m_vOrgPos = m_MoveCamera.position[m_nMovePositionIndex]; + StartTranslation( pView, vPoint ); + } + } + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button up event in the 2D view. +// Input : Per CWnd::OnLButtonUp. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnLMouseUp2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) +{ + ReleaseCapture(); + + if (IsTranslating()) + { + FinishTranslation(true); + + Vector viewPos, lookAt; + GetCameraPos( viewPos, lookAt ); + + m_pDocument->UpdateAllCameras( &viewPos, &lookAt, NULL ); + } + + m_pDocument->UpdateStatusbar(); + + return true; +} + +unsigned int Camera3D::GetConstraints(unsigned int nKeyFlags) +{ + unsigned int uConstraints = Tool3D::GetConstraints( nKeyFlags ); + + if(nKeyFlags & MK_CONTROL) + { + uConstraints |= constrainMoveAll; + } + + return uConstraints; +} + +//----------------------------------------------------------------------------- +// Purpose: Handles the mouse move event in the 2D view. +// Input : Per CWnd::OnMouseMove. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnMouseMove2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint) +{ + CMapDoc *pDoc = pView->GetMapDoc(); + if (!pDoc) + { + return true; + } + + vgui::HCursor hCursor = vgui::dc_arrow; + + unsigned int uConstraints = GetConstraints( nFlags ); + + // Make sure the point is visible. + + pView->ToolScrollToPoint( vPoint ); + + // + // Convert to world coords. + // + Vector vecWorld; + pView->ClientToWorld(vecWorld, vPoint); + + // + // Update status bar position display. + // + char szBuf[128]; + + m_pDocument->Snap(vecWorld,uConstraints); + + sprintf(szBuf, " @%.0f, %.0f ", vecWorld[pView->axHorz], vecWorld[pView->axVert] ); + SetStatusText(SBI_COORDS, szBuf); + + if (IsTranslating()) + { + Tool3D::UpdateTranslation(pView, vPoint, uConstraints ); + + hCursor = vgui::dc_none; + } + else if ( !IsEmpty() ) + { + // + // If the cursor is on a handle, set it to a cross. + // + if ( HitTest( pView, vPoint, true) ) + { + hCursor = vgui::dc_crosshair; + } + } + + if ( hCursor != vgui::dc_none ) + pView->SetCursor( hCursor ); + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button down event in the 3D view. +// Input : Per CWnd::OnLButtonDown. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + pView->EnableRotating(true); + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse up down event in the 3D view. +// Input : Per CWnd::OnLButtonUp. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnLMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + pView->EnableRotating(false); + pView->UpdateCameraVariables(); + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the right mouse button down event in the 3D view. +// Input : Per CWnd::OnRButtonDown. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnRMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + pView->EnableStrafing(true); + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the right mouse button up event in the 3D view. +// Input : Per CWnd::OnRButtonUp. +// Output : Returns true if the message was handled, false if not. +//----------------------------------------------------------------------------- +bool Camera3D::OnRMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint) +{ + pView->EnableStrafing(false); + pView->UpdateCameraVariables(); + return true; +} + + +//----------------------------------------------------------------------------- +// 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 Camera3D::OnKeyDown3D(CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags) +{ + if (nChar == VK_DELETE || nChar == VK_NEXT || nChar == VK_PRIOR) + { + CMapDoc *pDoc = pView->GetMapDoc(); + + if (nChar == VK_DELETE) + { + DeleteActiveCamera(); + } + else if (nChar == VK_NEXT) + { + SetNextCamera(Camera3D::sncNext); + } + else + { + SetNextCamera(Camera3D::sncPrev); + } + + Vector viewPos, lookAt; + GetCameraPos( viewPos, lookAt ); + + pDoc->UpdateAllCameras( &viewPos, &lookAt, NULL ); + + return true; + } + else if (nChar == VK_ESCAPE) + { + OnEscape(); + return true; + } + + return false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the escape key in the 2D or 3D views. +//----------------------------------------------------------------------------- +void Camera3D::OnEscape(void) +{ + // + // Stop using the camera tool. + // + m_pDocument->GetTools()->SetTool(TOOL_POINTER); +} + |