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/mapview3d.cpp | |
| download | archived-source-engine-2018-hl2-src-master.tar.xz archived-source-engine-2018-hl2-src-master.zip | |
Diffstat (limited to 'hammer/mapview3d.cpp')
| -rw-r--r-- | hammer/mapview3d.cpp | 2049 |
1 files changed, 2049 insertions, 0 deletions
diff --git a/hammer/mapview3d.cpp b/hammer/mapview3d.cpp new file mode 100644 index 0000000..3a2edf3 --- /dev/null +++ b/hammer/mapview3d.cpp @@ -0,0 +1,2049 @@ +//========= Copyright Valve Corporation, All rights reserved. ============// +// +// Purpose: Implements the 3D view message handling. This class is responsible +// for 3D camera control, activating tools in the 3D view, calling +// into the renderer when necessary, and synchronizing the 2D camera +// information with the 3D camera. +// +//=============================================================================// + +#include "stdafx.h" +#include <oleauto.h> +#include <oaidl.h> +#if _MSC_VER < 1300 +#include <afxpriv.h> +#endif +#include <mmsystem.h> +#include "Camera.h" +#include "GlobalFunctions.h" +#include "Gizmo.h" +#include "History.h" +#include "Keyboard.h" +#include "MainFrm.h" +#include "MapDoc.h" +#include "MapDecal.h" +#include "MapEntity.h" +#include "MapSolid.h" +#include "MapStudioModel.h" +#include "MapWorld.h" +#include "MapView3D.h" +#include "MapView2D.h" +#include "ObjectBar.h" +#include "Options.h" +#include "StatusBarIDs.h" +#include "TitleWnd.h" +#include "ToolManager.h" +#include "hammer.h" +#include "mathlib/vector.h" +#include "MapOverlay.h" +#include "engine_launcher_api.h" +#include "vgui/Cursor.h" +#include "ToolCamera.h" +#include "HammerVGui.h" +// memdbgon must be the last include file in a .cpp file!!! +#include <tier0/memdbgon.h> + +#pragma warning(disable:4244 4305) + + +typedef struct +{ + CMapObjectList *pList; + POINT pt; + CMapWorld *pWorld; +} SELECT3DINFO; + + +int g_nClipPoints = 0; +Vector g_ClipPoints[4]; + + +// +// Defines the logical keys. +// +#define LOGICAL_KEY_FORWARD 0 +#define LOGICAL_KEY_BACK 1 +#define LOGICAL_KEY_LEFT 2 +#define LOGICAL_KEY_RIGHT 3 +#define LOGICAL_KEY_UP 4 +#define LOGICAL_KEY_DOWN 5 +#define LOGICAL_KEY_PITCH_UP 6 +#define LOGICAL_KEY_PITCH_DOWN 7 +#define LOGICAL_KEY_YAW_LEFT 8 +#define LOGICAL_KEY_YAW_RIGHT 9 + +// +// Rotation speeds, in degrees per second. +// +#define YAW_SPEED 180 +#define PITCH_SPEED 180 +#define ROLL_SPEED 180 + + +IMPLEMENT_DYNCREATE(CMapView3D, CView) + + +BEGIN_MESSAGE_MAP(CMapView3D, CView) + //{{AFX_MSG_MAP(CMapView3D) + ON_WM_KILLFOCUS() + ON_WM_TIMER() + ON_WM_KEYDOWN() + ON_WM_KEYUP() + ON_WM_SIZE() + ON_WM_CONTEXTMENU() + ON_WM_LBUTTONDOWN() + ON_WM_LBUTTONUP() + ON_WM_LBUTTONDBLCLK() + ON_WM_RBUTTONDOWN() + ON_WM_MOUSEMOVE() + ON_WM_MOUSEWHEEL() + ON_WM_RBUTTONUP() + ON_WM_CHAR() + ON_WM_SETFOCUS() + ON_WM_NCPAINT() + ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint) + ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview) + ON_COMMAND(ID_VIEW_3DWIREFRAME, OnView3dWireframe) + ON_COMMAND(ID_VIEW_3DPOLYGON, OnView3dPolygon) + ON_COMMAND(ID_VIEW_3DTEXTURED, OnView3dTextured) + ON_COMMAND(ID_VIEW_3DLIGHTMAP_GRID, OnView3dLightmapGrid) + ON_COMMAND(ID_VIEW_LIGHTINGPREVIEW, OnView3dLightingPreview) + ON_COMMAND(ID_VIEW_LIGHTINGPREVIEW_RAYTRACED, OnView3dLightingPreviewRayTraced) + //}}AFX_MSG_MAP +END_MESSAGE_MAP() + + +//----------------------------------------------------------------------------- +// Purpose: Constructor. Initializes data members to default values. +//----------------------------------------------------------------------------- +CMapView3D::CMapView3D(void) +{ + m_eDrawType = VIEW3D_WIREFRAME; + m_pRender = NULL; + m_pCamera = NULL; + + m_dwTimeLastInputSample = 0; + + m_fForwardSpeed = 0; + m_fStrafeSpeed = 0; + m_fVerticalSpeed = 0; + + m_pwndTitle = NULL; + m_bLightingPreview = false; + + m_bMouseLook = false; + m_bStrafing = false; + m_bRotating = false; + + m_ptLastMouseMovement.x = 0; + m_ptLastMouseMovement.y = 0; + + m_nLastRaytracedBitmapRenderTimeStamp = -1; + + m_bCameraPosChanged = false; + m_bClippingChanged = false; +} + + +//----------------------------------------------------------------------------- +// Purpose: Destructor. Releases dynamically allocated resources. +//----------------------------------------------------------------------------- +CMapView3D::~CMapView3D(void) +{ + if (m_pCamera != NULL) + { + delete m_pCamera; + } + + if (m_pRender != NULL) + { + m_pRender->ShutDown(); + delete m_pRender; + } + + if (m_pwndTitle != NULL) + { + delete m_pwndTitle; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : cs - +// Output : Returns TRUE on success, FALSE on failure. +//----------------------------------------------------------------------------- +BOOL CMapView3D::PreCreateWindow(CREATESTRUCT& cs) +{ + static CString className; + + if(className.IsEmpty()) + { + // + // We need the CS_OWNDC bit so that we don't need to call GetDC every time we render. That fixes the flicker under Win98. + // + className = AfxRegisterWndClass(CS_BYTEALIGNCLIENT | CS_DBLCLKS | CS_HREDRAW | CS_VREDRAW | CS_OWNDC, NULL, HBRUSH(GetStockObject(BLACK_BRUSH))); + } + + cs.lpszClass = className; + + return CView::PreCreateWindow(cs); +} + + +//----------------------------------------------------------------------------- +// Purpose: Disables mouselook when the view loses focus. This ensures that the +// cursor is shown and not locked in the center of the 3D view. +// Input : pNewWnd - The window getting focus. +//----------------------------------------------------------------------------- +void CMapView3D::OnKillFocus(CWnd *pNewWnd) +{ + EnableMouseLook(false); + EnableRotating(false); + EnableStrafing(false); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nDrawType - +//----------------------------------------------------------------------------- +void CMapView3D::SetDrawType(DrawType_t eDrawType) +{ + EditorRenderMode_t eRenderMode; + + // Turn off the dialog. + if ( m_eDrawType == VIEW3D_SMOOTHING_GROUP ) + { + CMainFrame *pMainFrame = GetMainWnd(); + if ( pMainFrame ) + { + CFaceSmoothingVisualDlg *pSmoothDlg = pMainFrame->GetSmoothingGroupDialog(); + pSmoothDlg->ShowWindow( SW_HIDE ); + } + } + + if (m_pwndTitle != NULL) + { + m_pwndTitle->SetTitle("camera"); + } + + m_bLightingPreview = false; + switch (eDrawType) + { + case VIEW3D_WIREFRAME: + { + eRenderMode = RENDER_MODE_WIREFRAME; + break; + } + + case VIEW3D_POLYGON: + { + eRenderMode = RENDER_MODE_FLAT; + break; + } + + case VIEW3D_TEXTURED: + { + eRenderMode = RENDER_MODE_TEXTURED; + break; + } + + case VIEW3D_TEXTURED_SHADED: + { + eRenderMode = RENDER_MODE_TEXTURED_SHADED; + break; + } + case VIEW3D_LIGHTMAP_GRID: + { + eRenderMode = RENDER_MODE_LIGHTMAP_GRID; + break; + } + + case VIEW3D_LIGHTING_PREVIEW2: + { + eRenderMode = RENDER_MODE_LIGHT_PREVIEW2; + break; + } + + case VIEW3D_LIGHTING_PREVIEW_RAYTRACED: + { + eRenderMode = RENDER_MODE_LIGHT_PREVIEW_RAYTRACED; + break; + } + + case VIEW3D_SMOOTHING_GROUP: + { + CMainFrame *pMainFrame = GetMainWnd(); + if ( pMainFrame ) + { + CFaceSmoothingVisualDlg *pSmoothDlg = pMainFrame->GetSmoothingGroupDialog(); + pSmoothDlg->ShowWindow( SW_SHOW ); + } + + // Always set the initial group to visualize (zero). + CMapDoc *pDoc = GetMapDoc(); + pDoc->SetSmoothingGroupVisual( 0 ); + + eRenderMode = RENDER_MODE_SMOOTHING_GROUP; + break; + } + + //case VIEW3D_ENGINE: + //{ + // eRenderMode = RENDER_MODE_TEXTURED; + // if ( IsRunningInEngine() ) + // { + // CMapDoc *pMapDoc = CMapDoc::GetActiveMapDoc(); + // if ( pMapDoc ) + // { + // const char *pFullPathName = pMapDoc->GetPathName(); + // if ( pFullPathName && pFullPathName[0] ) + // { + // char buf[MAX_PATH]; + // Q_FileBase( pFullPathName, buf, MAX_PATH ); + // + // // Don't do it if we're untitled + // //if ( !Q_stristr( buf, "untitled" ) ) + // { + // g_pEngineAPI->SetEngineWindow( m_hWnd ); + // //g_pEngineAPI->SetMap( buf ); + // g_pEngineAPI->ActivateSimulation( true ); + // } + // } + // } + // } + // if (m_pwndTitle != NULL) + // { + // m_pwndTitle->SetTitle("engine"); + // } + // break; + //} + + default: + { + Assert(FALSE); + eDrawType = VIEW3D_WIREFRAME; + eRenderMode = RENDER_MODE_WIREFRAME; + break; + } + } + + m_eDrawType = eDrawType; + + // + // Set renderer to use the new rendering mode. + // + if (m_pRender != NULL) + { + m_pRender->SetDefaultRenderMode(eRenderMode); + m_pRender->SetInLightingPreview( m_bLightingPreview ); + + // Somehow, this drop down box screws up MFC's notion + // of what we're supposed to be updating. This is a workaround. + m_pRender->ResetFocus(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets the position and direction of the camera for this view. +//----------------------------------------------------------------------------- +void CMapView3D::SetCamera(const Vector &vecPos, const Vector &vecLookAt) +{ + m_pCamera->SetViewPoint(vecPos); + m_pCamera->SetViewTarget(vecLookAt); +} + +//----------------------------------------------------------------------------- +// Purpose: Prepares to print. +// Input : Per CView::OnPreparePrinting. +// Output : Returns nonzero to begin printing, zero to cancel printing. +//----------------------------------------------------------------------------- +BOOL CMapView3D::OnPreparePrinting(CPrintInfo* pInfo) +{ + return(DoPreparePrinting(pInfo)); +} + + +//----------------------------------------------------------------------------- +// Purpose: Debugging functions. +//----------------------------------------------------------------------------- +#ifdef _DEBUG +void CMapView3D::AssertValid() const +{ + CView::AssertValid(); +} + +void CMapView3D::Dump(CDumpContext& dc) const +{ + CView::Dump(dc); +} +#endif //_DEBUG + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nIDEvent - +//----------------------------------------------------------------------------- +void CMapView3D::OnTimer(UINT nIDEvent) +{ + static bool s_bPicking = false; // picking mutex + + switch (nIDEvent) + { + case MVTIMER_PICKNEXT: + { + if ( !s_bPicking ) + { + s_bPicking = true; + // set current document hit + GetMapDoc()->GetSelection()->SetCurrentHit(hitNext); + s_bPicking = false; + } + break; + } + } + + CView::OnTimer(nIDEvent); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called just before we are destroyed. +//----------------------------------------------------------------------------- +BOOL CMapView3D::DestroyWindow() +{ + KillTimer(MVTIMER_PICKNEXT); + return CView::DestroyWindow(); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapView3D::UpdateStatusBar(void) +{ + if (!IsWindow(m_hWnd)) + { + return; + } + + SetStatusText(SBI_GRIDZOOM, ""); + SetStatusText(SBI_COORDS, ""); +} + + +//----------------------------------------------------------------------------- +// Purpose: Sets up key bindings for the 3D view. +//----------------------------------------------------------------------------- +void CMapView3D::InitializeKeyMap(void) +{ + m_Keyboard.RemoveAllKeyMaps(); + + if (!Options.view2d.bNudge) + { + m_Keyboard.AddKeyMap(VK_LEFT, 0, LOGICAL_KEY_YAW_LEFT); + m_Keyboard.AddKeyMap(VK_RIGHT, 0, LOGICAL_KEY_YAW_RIGHT); + m_Keyboard.AddKeyMap(VK_DOWN, 0, LOGICAL_KEY_PITCH_DOWN); + m_Keyboard.AddKeyMap(VK_UP, 0, LOGICAL_KEY_PITCH_UP); + + m_Keyboard.AddKeyMap(VK_LEFT, KEY_MOD_SHIFT, LOGICAL_KEY_LEFT); + m_Keyboard.AddKeyMap(VK_RIGHT, KEY_MOD_SHIFT, LOGICAL_KEY_RIGHT); + m_Keyboard.AddKeyMap(VK_DOWN, KEY_MOD_SHIFT, LOGICAL_KEY_DOWN); + m_Keyboard.AddKeyMap(VK_UP, KEY_MOD_SHIFT, LOGICAL_KEY_UP); + } + + if (Options.view3d.bUseMouseLook) + { + m_Keyboard.AddKeyMap('W', 0, LOGICAL_KEY_FORWARD); + m_Keyboard.AddKeyMap('A', 0, LOGICAL_KEY_LEFT); + m_Keyboard.AddKeyMap('D', 0, LOGICAL_KEY_RIGHT); + m_Keyboard.AddKeyMap('S', 0, LOGICAL_KEY_BACK); + } + else + { + m_Keyboard.AddKeyMap('D', 0, LOGICAL_KEY_FORWARD); + m_Keyboard.AddKeyMap('C', 0, LOGICAL_KEY_BACK); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pWnd - +// point - +//----------------------------------------------------------------------------- +void CMapView3D::OnContextMenu(CWnd *pWnd, CPoint point) +{ + // Pass the message to the active tool. + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool) + { + if ( pTool->OnContextMenu3D(this, 0, Vector2D(point.x, point.y) ) ) + { + return; + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the key down event. +// Input : Per CWnd::OnKeyDown. +//----------------------------------------------------------------------------- +void CMapView3D::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + CMapDoc *pDoc = GetMapDoc(); + if (pDoc == NULL) + { + return; + } + + // + // 'z' toggles mouselook. + // + if (((char)tolower(nChar) == 'z') && !(nFlags & 0x4000) && (Options.view3d.bUseMouseLook)) + { + if (pDoc != NULL) + { + EnableMouseLook(!m_bMouseLook); + + // + // If we just stopped mouse looking, update the camera variables. + // + if (!m_bMouseLook) + { + UpdateCameraVariables(); + } + } + + return; + } + + // Got to check for m_pToolManager here because otherwise it can crash on startup if they have keys pressed. + if ( m_pToolManager ) + { + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool) + { + if (pTool->OnKeyDown3D(this, nChar, nRepCnt, nFlags)) + { + return; + } + } + } + + m_Keyboard.OnKeyDown(nChar, nRepCnt, nFlags); + + switch (nChar) + { + case VK_DELETE: + { + pDoc->OnCmdMsg(ID_EDIT_DELETE, CN_COMMAND, NULL, NULL); + break; + } + + case VK_NEXT: + { + pDoc->OnCmdMsg(ID_EDIT_SELNEXT, CN_COMMAND, NULL, NULL); + break; + } + + case VK_PRIOR: + { + pDoc->OnCmdMsg(ID_EDIT_SELPREV, CN_COMMAND, NULL, NULL); + break; + } + + // + // Move the back clipping plane closer in. + // + case '1': + { + float fBack = m_pCamera->GetFarClip(); + if (fBack >= 2000) + { + m_pCamera->SetFarClip(fBack - 1000); + Options.view3d.iBackPlane = fBack; + } + else if (fBack > 500) + { + m_pCamera->SetFarClip(fBack - 250); + Options.view3d.iBackPlane = fBack; + } + m_bUpdateView = true; + m_bClippingChanged = true; + break; + } + + // + // Move the back clipping plane farther away. + // + case '2': + { + float fBack = m_pCamera->GetFarClip(); + if ((fBack <= 9000) && (fBack > 1000)) + { + m_pCamera->SetFarClip(fBack + 1000); + Options.view3d.iBackPlane = fBack; + } + else if (fBack < 10000) + { + m_pCamera->SetFarClip(fBack + 250); + Options.view3d.iBackPlane = fBack; + } + m_bUpdateView = true; + m_bClippingChanged = true; + break; + } + + case 'O': + case 'o': + { + m_pRender->DebugHook1(); + break; + } + + case 'I': + case 'i': + { + m_pRender->DebugHook2(); + break; + } + + case 'P': + case 'p': + { + pDoc->OnToggle3DGrid(); + break; + } + + default: + { + break; + } + } + + CView::OnKeyDown(nChar, nRepCnt, nFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles key release events. +// Input : Per CWnd::OnKeyup +//----------------------------------------------------------------------------- +void CMapView3D::OnKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // Got to check for m_pToolManager here because otherwise it can crash on startup if they have keys pressed. + if ( m_pToolManager ) + { + // Pass the message to the active tool. + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool) + { + if (pTool->OnKeyUp3D(this, nChar, nRepCnt, nFlags)) + { + return; + } + } + + m_Keyboard.OnKeyUp(nChar, nRepCnt, nFlags); + + UpdateCameraVariables(); + } + + CView::OnKeyUp(nChar, nRepCnt, nFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called when the view is resized. +// Input : nType - +// cx - +// cy - +//----------------------------------------------------------------------------- +void CMapView3D::OnSize(UINT nType, int cx, int cy) +{ + if ( m_pCamera ) + { + m_pCamera->SetViewPort( cx, cy ); + } + + CView::OnSize(nType, cx, cy); +} + + +//----------------------------------------------------------------------------- +// Purpose: Finds the axis that is most closely aligned with the given vector. +// Input : Vector - Vector to find closest axis to. +// Output : Returns an axis index as follows: +// 0 - Positive X axis. +// 1 - Positive Y axis. +// 2 - Positive Z axis. +// 3 - Negative X axis. +// 4 - Negative Y axis. +// 5 - Negative Z axis. +//----------------------------------------------------------------------------- +const Vector&ClosestAxis(const Vector& v) +{ + static Vector vBestAxis; + float fBestDot = -1; + Vector vNormal = v; + + VectorNormalize( vNormal ); + vBestAxis.Init(); + + for (int i = 0; i < 6; i++) + { + Vector vTestAxis(0,0,0); + + vTestAxis[i%3] = (i>=3)?-1:1; + + float fTestDot = DotProduct(v, vTestAxis); + if (fTestDot > fBestDot) + { + fBestDot = fTestDot; + vBestAxis = vTestAxis; + } + } + + return vBestAxis; +} + +void CMapView3D::GetBestTransformPlane( Vector &horzAxis, Vector &vertAxis, Vector &thirdAxis) +{ + Vector vAxis; + + m_pCamera->GetViewRight( vAxis ); + horzAxis = ClosestAxis( vAxis ); + + m_pCamera->GetViewUp( vAxis ); + vertAxis = ClosestAxis( vAxis ); + + m_pCamera->GetViewForward( vAxis ); + thirdAxis = ClosestAxis( vAxis ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Synchronizes the 2D camera information with the 3D view. +//----------------------------------------------------------------------------- +void CMapView3D::UpdateCameraVariables(void) +{ + Camera3D *pCamTool = dynamic_cast<Camera3D*>(m_pToolManager->GetToolForID( TOOL_CAMERA )); + + if (!m_pCamera || !pCamTool ) + return; + + Vector viewPoint,viewForward; + + m_pCamera->GetViewPoint(viewPoint); + m_pCamera->GetViewForward(viewForward); + + // tell camera tool to update active camera + pCamTool->UpdateActiveCamera( viewPoint, viewForward ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button double click event. +//----------------------------------------------------------------------------- +void CMapView3D::OnLButtonDblClk(UINT nFlags, CPoint point) +{ + // + // Don't forward message if we are controlling the camera. + // + if ((GetAsyncKeyState(VK_SPACE) & 0x8000) != 0) + { + return; + } + + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnLMouseDblClk3D( this, nFlags, vPoint )) + { + return; + } + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles the left mouse button down event. +//----------------------------------------------------------------------------- +void CMapView3D::OnLButtonDown(UINT nFlags, CPoint point) +{ + if ((GetAsyncKeyState(VK_SPACE) & 0x8000) != 0) + { + EnableRotating(true); + return; + } + + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnLMouseDown3D(this, nFlags, vPoint)) + { + return; + } + } + + CView::OnLButtonDown(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called by the selection tool to begin timed selection by depth. +//----------------------------------------------------------------------------- +void CMapView3D::BeginPick(void) +{ + SetTimer(MVTIMER_PICKNEXT, 500, NULL); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called by the selection tool to end timed selection by depth. +//----------------------------------------------------------------------------- +void CMapView3D::EndPick(void) +{ + // + // Kill pick timer. + // + KillTimer(MVTIMER_PICKNEXT); +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : nFlags - +// point - +//----------------------------------------------------------------------------- +void CMapView3D::OnLButtonUp(UINT nFlags, CPoint point) +{ + if (m_bRotating) + { + EnableRotating(false); + UpdateCameraVariables(); + return; + } + + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnLMouseUp3D(this, nFlags, vPoint)) + { + return; + } + } + + CView::OnLButtonUp(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: Creates the renderer and the camera and initializes them. +//----------------------------------------------------------------------------- +void CMapView3D::OnInitialUpdate(void) +{ + InitializeKeyMap(); + + // + // Create a title window. + // + m_pwndTitle = CTitleWnd::CreateTitleWnd(this, ID_2DTITLEWND); + Assert(m_pwndTitle != NULL); + if (m_pwndTitle != NULL) + { + m_pwndTitle->SetTitle("camera"); + } + + // + // CMainFrame::LoadWindowStates calls InitialUpdateFrame which causes us to get two + // OnInitialUpdate messages! Check for a NULL renderer to avoid processing twice. + // + if (m_pRender != NULL) + { + return; + } + + // + // Create and initialize the renderer. + // + m_pRender = new CRender3D(); + + CMapDoc *pDoc = GetMapDoc(); + if (pDoc == NULL) + { + Assert(pDoc != NULL); + return; + } + + m_pRender->SetView( this ); + + m_pToolManager = pDoc->GetTools(); + + SetDrawType(m_eDrawType); + + + // + // Create and initialize the camera. + // + m_pCamera = new CCamera(); + Assert(m_pCamera != NULL); + if (m_pCamera == NULL) + { + return; + } + + CRect rect; + GetClientRect( rect ); + m_pCamera->SetViewPort( rect.Width(), rect.Height() ); + + m_fForwardSpeedMax = Options.view3d.nForwardSpeedMax; + m_fStrafeSpeedMax = Options.view3d.nForwardSpeedMax * 0.75f; + m_fVerticalSpeedMax = Options.view3d.nForwardSpeedMax * 0.5f; + + // + // Calculate the acceleration based on max speed and the time to max speed. + // + if (Options.view3d.nTimeToMaxSpeed != 0) + { + m_fForwardAcceleration = m_fForwardSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + m_fStrafeAcceleration = m_fStrafeSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + m_fVerticalAcceleration = m_fVerticalSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + } + else + { + m_fForwardAcceleration = 0; + m_fStrafeAcceleration = 0; + m_fVerticalAcceleration = 0; + } + + // + // Set up the frustum. We set the vertical FOV to zero because the renderer + // only uses the horizontal FOV. + // + if ( Options.general.bRadiusCulling ) + { + // Hack! Don't use frustum culling when doing radial distance culling (slam the distance to 10K) + m_pCamera->SetPerspective( Options.view3d.fFOV, CAMERA_FRONT_PLANE_DISTANCE, 10000); + } + else + { + m_pCamera->SetPerspective( Options.view3d.fFOV, CAMERA_FRONT_PLANE_DISTANCE, Options.view3d.iBackPlane); + } + + // + // Set the distance at which studio models become bounding boxes. + // + CMapStudioModel::SetRenderDistance(Options.view3d.nModelDistance); + CMapStudioModel::EnableAnimation(Options.view3d.bAnimateModels); + + // + // Enable or disable reverse selection. + // + m_pRender->RenderEnable(RENDER_REVERSE_SELECTION, (Options.view3d.bReverseSelection == TRUE)); + + // + // Enable or disable the 3D grid. + // + m_pRender->RenderEnable(RENDER_GRID, pDoc->Is3DGridEnabled()); + + // + // Enable or disable texture filtering. + // + m_pRender->RenderEnable(RENDER_FILTER_TEXTURES, (Options.view3d.bFilterTextures == TRUE)); + + // Get the initial viewpoint and view direction from the default camera in the document. + + Camera3D *pCamTool = dynamic_cast<Camera3D*>(m_pToolManager->GetToolForID( TOOL_CAMERA )); + if ( pCamTool ) + { + Vector vecPos,vecLookAt; + pCamTool->GetCameraPos( vecPos,vecLookAt ); + SetCamera(vecPos, vecLookAt); + } + + CView::OnInitialUpdate(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Turns on wireframe mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +void CMapView3D::OnView3dWireframe(void) +{ + SetDrawType(VIEW3D_WIREFRAME); +} + + +//----------------------------------------------------------------------------- +// Purpose: Turns on flat shaded mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +void CMapView3D::OnView3dPolygon(void) +{ + SetDrawType(VIEW3D_POLYGON); +} + + +//----------------------------------------------------------------------------- +// Purpose: Turns on textured mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +void CMapView3D::OnView3dTextured(void) +{ + SetDrawType(VIEW3D_TEXTURED); +} + + +//----------------------------------------------------------------------------- +// Purpose: Turns on lightmap grid mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +void CMapView3D::OnView3dLightmapGrid(void) +{ + SetDrawType(VIEW3D_LIGHTMAP_GRID); +} + + +//----------------------------------------------------------------------------- +// Purpose: Turns on lighting preview mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +void CMapView3D::OnView3dLightingPreview(void) +{ + SetDrawType(VIEW3D_LIGHTING_PREVIEW2); +} + +void CMapView3D::OnView3dLightingPreviewRayTraced(void) +{ + SetDrawType(VIEW3D_LIGHTING_PREVIEW_RAYTRACED); +} + +//----------------------------------------------------------------------------- +// Purpose: Turns on engine mode from the floating "Camera" menu. +//----------------------------------------------------------------------------- +//void CMapView3D::OnView3dEngine(void) +//{ +// SetDrawType(VIEW3D_ENGINE); +//} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : bActivate - +// pActivateView - +// pDeactiveView - +//----------------------------------------------------------------------------- +void CMapView3D::ActivateView(bool bActivate) +{ + CMapView::ActivateView(bActivate); + + if (bActivate) + { + CMapDoc *pDoc = GetMapDoc(); + CMapDoc::SetActiveMapDoc(pDoc); + + UpdateStatusBar(); + + // tell doc to update title + pDoc->UpdateTitle(this); + + m_Keyboard.ClearKeyStates(); + + // + // Reset the last input sample time. + // + m_dwTimeLastInputSample = 0; + } +} + +void CMapView3D::OnDraw(CDC *pDC) +{ + CWnd *focusWnd = GetForegroundWindow(); + + if ( focusWnd && focusWnd->ContinueModal() ) + { + // render the view now since were not running the main loop + RenderView(); + } + else + { + // just flag view to be update with next main loop + m_bUpdateView = true; + } +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +void CMapView3D::RenderView() +{ + Render(); + m_bUpdateView = false; +} + + +//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- +bool CMapView3D::ShouldRender() +{ + if ( m_eDrawType == VIEW3D_LIGHTING_PREVIEW_RAYTRACED ) + { + // check if we have new results from lpreview thread +// if ( m_nLastRaytracedBitmapRenderTimeStamp != +// GetUpdateCounter( EVTYPE_BITMAP_RECEIVED_FROM_LPREVIEW ) ) +// return true; + } + else + { + // don't animate ray traced displays + if ( Options.view3d.bAnimateModels ) + { + DWORD dwTimeElapsed = timeGetTime() - m_dwTimeLastRender; + + if ( (dwTimeElapsed/1000.0f) > 1.0f/20.0f) + { + m_bUpdateView = true; + } + } + } + return CMapView::ShouldRender(); +} + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pDC - +//----------------------------------------------------------------------------- +void CMapView3D::OnSetFocus(CWnd *pOldWnd) +{ + // Make sure the whole window region is marked as invalid + m_bUpdateView = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Called to paint the non client area of the window. +//----------------------------------------------------------------------------- +void CMapView3D::OnNcPaint(void) +{ + // Make sure the whole window region is marked as invalid + m_bUpdateView = true; +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : pSender - +// lHint - +// pHint - +//----------------------------------------------------------------------------- +void CMapView3D::UpdateView(int nFlags) +{ + if ( !m_pRender ) + return; + + if (nFlags & ( MAPVIEW_UPDATE_ONLY_2D | MAPVIEW_UPDATE_ONLY_LOGICAL ) ) + return; + + // + // One of the options in the 3D options page is changing. + // + if (nFlags & MAPVIEW_OPTIONS_CHANGED) + { + InitializeKeyMap(); + + CMapStudioModel::SetRenderDistance(Options.view3d.nModelDistance); + CMapStudioModel::EnableAnimation(Options.view3d.bAnimateModels); + + m_pRender->RenderEnable(RENDER_REVERSE_SELECTION, (Options.view3d.bReverseSelection == TRUE)); + + m_fForwardSpeedMax = Options.view3d.nForwardSpeedMax; + m_fStrafeSpeedMax = Options.view3d.nForwardSpeedMax * 0.75f; + m_fVerticalSpeedMax = Options.view3d.nForwardSpeedMax * 0.5f; + + // + // Calculate the acceleration based on max speed and the time to max speed. + // + if (Options.view3d.nTimeToMaxSpeed != 0) + { + m_fForwardAcceleration = m_fForwardSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + m_fStrafeAcceleration = m_fStrafeSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + m_fVerticalAcceleration = m_fVerticalSpeedMax / (Options.view3d.nTimeToMaxSpeed / 1000.0f); + } + else + { + m_fForwardAcceleration = 0; + m_fStrafeAcceleration = 0; + m_fVerticalAcceleration = 0; + } + + m_pCamera->SetPerspective( Options.view3d.fFOV, CAMERA_FRONT_PLANE_DISTANCE, Options.view3d.iBackPlane); + + CMapDoc *pDoc = GetMapDoc(); + if ((pDoc != NULL) && (m_pRender != NULL)) + { + m_pRender->RenderEnable(RENDER_GRID, pDoc->Is3DGridEnabled()); + m_pRender->RenderEnable(RENDER_FILTER_TEXTURES, (Options.view3d.bFilterTextures == TRUE)); + } + } + + if (nFlags & MAPVIEW_UPDATE_OBJECTS) + { + // dvs: could use this hint to update the octree + } + + CMapView::UpdateView( nFlags ); +} + + +//----------------------------------------------------------------------------- +// Purpose: Determines the object at the point (point.x, point.y) in the 3D view. +// Input : point - Point to use for hit test. +// ulFace - Index of face in object that was hit. +// Output : Returns a pointer to the CMapClass object at the coordinates, NULL if none. +//----------------------------------------------------------------------------- +CMapClass *CMapView3D::NearestObjectAt( const Vector2D &vPoint, ULONG &ulFace, unsigned int nFlags, VMatrix *pLocalMatrix ) +{ + ulFace = 0; + if (m_pRender == NULL) + { + return(NULL); + } + + HitInfo_t Hits; + + if (m_pRender->ObjectsAt( vPoint.x, vPoint.y, 1, 1, &Hits, 1, nFlags ) != 0) + { + // + // If they clicked on a solid, the index of the face they clicked on is stored + // in array index [1]. + // + CMapAtom *pObject = (CMapAtom *)Hits.pObject; + CMapSolid *pSolid = dynamic_cast<CMapSolid *>(pObject); + if ( pLocalMatrix != NULL ) + { + *pLocalMatrix = Hits.m_LocalMatrix; + } + if (pSolid != NULL) + { + ulFace = Hits.uData; + return(pSolid); + } + + return((CMapClass *)pObject); + } + + return(NULL); +} + + +//----------------------------------------------------------------------------- +// Purpose: Casts a ray from the viewpoint through the given plane and determines +// the point of intersection of the ray on the plane. +// Input : point - Point in client screen coordinates. +// plane - Plane being 'clicked' on. +// pos - Returns the point on the plane that projects to the given point. +//----------------------------------------------------------------------------- +void CMapView3D::GetHitPos(const Vector2D &point, PLANE &plane, Vector &pos) +{ + // + // Find the point they clicked on in world coordinates. It lies on the near + // clipping plane. + // + Vector ClickPoint; + + ClientToWorld( ClickPoint, point ); + + // + // Build a ray from the viewpoint through the point on the near clipping plane. + // + Vector ViewPoint; + Vector Ray; + m_pCamera->GetViewPoint(ViewPoint); + VectorSubtract(ClickPoint, ViewPoint, Ray); + + // + // Find the point of intersection of the ray with the given plane. + // + float t = DotProduct(plane.normal, ViewPoint) - plane.dist; + t = t / -DotProduct(plane.normal, Ray); + + pos = ViewPoint + t * Ray; +} + +bool CMapView3D::HitTest( const Vector2D &vPoint, const Vector& mins, const Vector& maxs) +{ + Vector vStart, vEnd; + int nFace; + BuildRay( vPoint, vStart, vEnd ); + return IntersectionLineAABBox( mins, maxs, vStart, vEnd, nFace ) >= 0.0f; +} + +//----------------------------------------------------------------------------- +// Purpose: Finds all objects under the given rectangular region in the view. +// Input : x - Client x coordinate. +// y - Client y coordinate. +// fWidth - Width of region in client pixels. +// fHeight - Height of region in client pixels. +// pObjects - Receives objects in the given region. +// nMaxObjects - Size of the array pointed to by pObjects. +// Output : Returns the number of objects in the given region. +//----------------------------------------------------------------------------- +int CMapView3D::ObjectsAt( const Vector2D &vPoint, HitInfo_t *pObjects, int nMaxObjects, unsigned int nFlags ) +{ + if (m_pRender != NULL) + { + return m_pRender->ObjectsAt( vPoint.x, vPoint.y, 1, 1, pObjects, nMaxObjects, nFlags ); + } + + return 0; +} + + +//----------------------------------------------------------------------------- +// Purpose: Makes sure that this view has focus if the mouse moves over it. +//----------------------------------------------------------------------------- +void CMapView3D::OnMouseMove(UINT nFlags, CPoint point) +{ + // + // Make sure we are the active view. + // + if (!IsActive()) + { + CMapDoc *pDoc = GetMapDoc(); + pDoc->SetActiveView(this); + } + + // + // If we are the active application, make sure this view has the input focus. + // + if (APP()->IsActiveApp()) + { + if (GetFocus() != this) + { + SetFocus(); + } + } + + + CView::OnMouseMove(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapView3D::ProcessInput(void) +{ + if (m_dwTimeLastInputSample == 0) + { + m_dwTimeLastInputSample = timeGetTime(); + } + + DWORD dwTimeNow = timeGetTime(); + + float fElapsedTime = (float)(dwTimeNow - m_dwTimeLastInputSample) / 1000.0f; + + m_dwTimeLastInputSample = dwTimeNow; + + // Clamp (can get really big when we cache textures in ) + if (fElapsedTime > 0.3f) + { + fElapsedTime = 0.3f; + } + else if ( fElapsedTime <=0 ) + { + return; // dont process input + } + + ProcessKeys( fElapsedTime ); + + ProcessMouse(); + + if ( Options.general.bRadiusCulling ) + { + ProcessCulling(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Applies an acceleration to a velocity, allowing instantaneous direction +// change and zeroing the velocity in the absence of acceleration. +// Input : fVelocity - Current velocity. +// fAccel - Amount of acceleration to apply. +// fTimeScale - The time for which the acceleration should be applied. +// fMaxVelocity - The maximum velocity to allow. +// Output : Returns the new velocity. +//----------------------------------------------------------------------------- +static float Accelerate(float fVelocity, float fAccel, float fAccelScale, float fTimeScale, float fVelocityMax) +{ + // + // If we have a finite acceleration in this direction, apply it to the velocity. + // + if ((fAccel != 0) && (fAccelScale != 0)) + { + // + // Check for direction reversal - zero velocity when reversing. + // + if (fAccelScale > 0) + { + if (fVelocity < 0) + { + fVelocity = 0; + } + } + else if (fAccelScale < 0) + { + if (fVelocity > 0) + { + fVelocity = 0; + } + } + + // + // Apply the acceleration. + // + fVelocity += fAccel * fAccelScale * fTimeScale; + if (fVelocity > fVelocityMax) + { + fVelocity = fVelocityMax; + } + else if (fVelocity < -fVelocityMax) + { + fVelocity = -fVelocityMax; + } + + } + // + // If we have infinite acceleration, go straight to maximum velocity. + // + else if (fAccelScale != 0) + { + fVelocity = fVelocityMax * fAccelScale; + } + // + // Else no velocity in this direction at all. + // + else + { + fVelocity = 0; + } + + return(fVelocity); +} + + +//----------------------------------------------------------------------------- +// Purpose: Moves the camera based on the keyboard state. +//----------------------------------------------------------------------------- +void CMapView3D::ProcessMovementKeys(float fElapsedTime) +{ + // + // Read the state of the camera movement keys. + // + float fBack = m_Keyboard.GetKeyScale(LOGICAL_KEY_BACK); + float fMoveForward = m_Keyboard.GetKeyScale(LOGICAL_KEY_FORWARD) - fBack; + + float fLeft = m_Keyboard.GetKeyScale(LOGICAL_KEY_LEFT); + float fMoveRight = m_Keyboard.GetKeyScale(LOGICAL_KEY_RIGHT) - fLeft; + + float fDown = m_Keyboard.GetKeyScale(LOGICAL_KEY_DOWN); + float fMoveUp = m_Keyboard.GetKeyScale(LOGICAL_KEY_UP) - fDown; + + float fPitchUp = m_Keyboard.GetKeyScale(LOGICAL_KEY_PITCH_UP); + float fPitchDown = m_Keyboard.GetKeyScale(LOGICAL_KEY_PITCH_DOWN); + + float fYawLeft = m_Keyboard.GetKeyScale(LOGICAL_KEY_YAW_LEFT); + float fYawRight = m_Keyboard.GetKeyScale(LOGICAL_KEY_YAW_RIGHT); + + // + // Apply pitch and yaw if they are nonzero. + // + if ((fPitchDown - fPitchUp) != 0) + { + m_pCamera->Pitch((fPitchDown - fPitchUp) * fElapsedTime * PITCH_SPEED); + m_bUpdateView = true; + } + + if ((fYawRight - fYawLeft) != 0) + { + m_pCamera->Yaw((fYawRight - fYawLeft) * fElapsedTime * YAW_SPEED); + m_bUpdateView = true; + } + + // + // Apply the accelerations to the forward, strafe, and vertical speeds. They are actually + // velocities because they are signed values. + // + m_fForwardSpeed = Accelerate(m_fForwardSpeed, m_fForwardAcceleration, fMoveForward, fElapsedTime, m_fForwardSpeedMax); + m_fStrafeSpeed = Accelerate(m_fStrafeSpeed, m_fStrafeAcceleration, fMoveRight, fElapsedTime, m_fStrafeSpeedMax); + m_fVerticalSpeed = Accelerate(m_fVerticalSpeed, m_fVerticalAcceleration, fMoveUp, fElapsedTime, m_fVerticalSpeedMax); + + // + // Move the camera if any of the speeds are nonzero. + // + if (m_fForwardSpeed != 0) + { + m_pCamera->MoveForward(m_fForwardSpeed * fElapsedTime); + m_bUpdateView = true; + m_bCameraPosChanged = true; + } + + if (m_fStrafeSpeed != 0) + { + m_pCamera->MoveRight(m_fStrafeSpeed * fElapsedTime); + m_bUpdateView = true; + m_bCameraPosChanged = true; + } + + if (m_fVerticalSpeed != 0) + { + m_pCamera->MoveUp(m_fVerticalSpeed * fElapsedTime); + m_bUpdateView = true; + m_bCameraPosChanged = true; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapView3D::ProcessKeys(float fElapsedTime) +{ + ProcessMovementKeys(fElapsedTime); + + m_Keyboard.ClearImpulseFlags(); +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +void CMapView3D::ProcessCulling( void ) +{ + if ( m_bCameraPosChanged || m_bClippingChanged ) + { + CMapDoc *pDoc = GetMapDoc(); + pDoc->UpdateVisibilityAll(); + + m_bClippingChanged = false; + m_bCameraPosChanged = false; + } +} + +//----------------------------------------------------------------------------- +// Purpose: +//----------------------------------------------------------------------------- +bool CMapView3D::ControlCamera(const CPoint &point) +{ + if (!m_bStrafing && !m_bRotating && !m_bMouseLook) + { + return false; + } + + bool bShift = ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0); + + CRect rect; + GetClientRect(&rect); + // get mouse distance to client window center + CPoint WindowCenter = rect.CenterPoint(); + CSize MouseLookDelta = point - WindowCenter; + + // camera look is on, but no mouse changes + if ( MouseLookDelta.cx == 0 && MouseLookDelta.cy == 0 ) + true; + + // + // If strafing, left-right movement moves the camera from side to side. + // Up-down movement either moves the camera forward and back if the SHIFT + // key is held down, or up and down if the SHIFT key is not held down. + // If rotating and strafing simultaneously, the behavior is as if SHIFT is + // held down. + // + if (m_bStrafing) + { + if (bShift || m_bRotating) + { + MoveForward(-MouseLookDelta.cy * 2); + } + else + { + MoveUp(-MouseLookDelta.cy * 2); + } + + MoveRight(MouseLookDelta.cx * 2); + + m_bCameraPosChanged = true; + } + // + // If mouse looking, left-right movement controls yaw, and up-down + // movement controls pitch. + // + else + { + // + // Up-down mouse movement changes the camera pitch. + // + if (MouseLookDelta.cy) + { + float fTheta = MouseLookDelta.cy * 0.4; + if (Options.view3d.bReverseY) + { + fTheta = -fTheta; + } + + Pitch(fTheta); + } + + // + // Left-right mouse movement changes the camera yaw. + // + if (MouseLookDelta.cx) + { + float fTheta = MouseLookDelta.cx * 0.4; + Yaw(fTheta); + } + } + + // move mouse back to center + CWnd::ClientToScreen(&WindowCenter); + SetCursorPos(WindowCenter.x, WindowCenter.y); + m_bUpdateView = true; + + return true; +} + + +//----------------------------------------------------------------------------- +// Purpose: Called by RunFrame to tell this view to process mouse input. This +// function samples the cursor position and takes the appropriate +// action based on the current mode (camera, morphing). +//----------------------------------------------------------------------------- +void CMapView3D::ProcessMouse(void) +{ + // + // Get the cursor position in client coordinates. + // + + CPoint point; + GetCursorPos(&point); + ScreenToClient(&point); + + if ( point == m_ptLastMouseMovement ) + return; + + m_ptLastMouseMovement = point; + + if ( ControlCamera( point ) ) + { + return; + } + + // If not in mouselook mode, only process mouse messages if there + // is an active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + // + // Pass the message to the tool. + // + + int nFlags = 0; + + if ((GetAsyncKeyState(VK_CONTROL) & 0x8000) != 0) + { + nFlags |= MK_CONTROL; + } + + if ((GetAsyncKeyState(VK_SHIFT) & 0x8000) != 0) + { + nFlags |= MK_SHIFT; + } + + Vector2D vPoint( point.x,point.y); + pTool->OnMouseMove3D(this, nFlags, vPoint); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles mouse wheel events. The mouse wheel is used in camera mode +// to dolly the camera forward and back. +// Input : Per CWnd::OnMouseWheel. +//----------------------------------------------------------------------------- +BOOL CMapView3D::OnMouseWheel(UINT nFlags, short zDelta, CPoint point) +{ + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnMouseWheel3D(this, nFlags, zDelta, vPoint)) + { + return(TRUE); + } + } + + m_pCamera->MoveForward(zDelta / 2); + + // + // Render now to avoid an ugly lag between the 2D views and the 3D view + // when "center 2D views on camera" is enabled. + // + m_bUpdateView = true; + m_bCameraPosChanged = true; + + UpdateCameraVariables(); + + return CView::OnMouseWheel(nFlags, zDelta, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles right mouse button down events. +// Input : Per CWnd::OnRButtonDown. +//----------------------------------------------------------------------------- +void CMapView3D::OnRButtonDown(UINT nFlags, CPoint point) +{ + if ((GetAsyncKeyState(VK_SPACE) & 0x8000) != 0) + { + EnableStrafing(true); + return; + } + + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnRMouseDown3D( this, nFlags, vPoint )) + { + return; + } + } + + CView::OnRButtonDown(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles right mouse button up events. +// Input : Per CWnd::OnRButtonUp. +//----------------------------------------------------------------------------- +void CMapView3D::OnRButtonUp(UINT nFlags, CPoint point) +{ + if (m_bStrafing) + { + // + // Turn off strafing and update the 2D views. + // + EnableStrafing(false); + UpdateCameraVariables(); + return; + } + + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + Vector2D vPoint( point.x,point.y); + if (pTool->OnRMouseUp3D( this, nFlags, vPoint )) + { + return; + } + } + + CView::OnRButtonUp(nFlags, point); +} + + +//----------------------------------------------------------------------------- +// Purpose: Handles character events. +// Input : Per CWnd::OnChar. +//----------------------------------------------------------------------------- +void CMapView3D::OnChar(UINT nChar, UINT nRepCnt, UINT nFlags) +{ + // Got to check for m_pToolManager here because otherwise it can crash on startup if they have keys pressed. + if ( m_pToolManager ) + { + // + // Pass the message to the active tool. + // + CBaseTool *pTool = m_pToolManager->GetActiveTool(); + if (pTool != NULL) + { + if (pTool->OnChar3D(this, nChar, nRepCnt, nFlags)) + { + return; + } + } + } + + CView::OnChar(nChar, nRepCnt, nFlags); +} + + +//----------------------------------------------------------------------------- +// Purpose: Called when mouselook is enabled. The cursor is moved to the center +// of the screen and hidden. +// Input : bEnable - true to lock and hide the cursor, false to unlock and show it. +//----------------------------------------------------------------------------- +void CMapView3D::EnableCrosshair(bool bEnable) +{ + CRect Rect; + CPoint Point; + + GetClientRect(&Rect); + CWnd::ClientToScreen(&Rect); + Point = Rect.CenterPoint(); + SetCursorPos(Point.x, Point.y); + + if (bEnable) + { + ClipCursor(&Rect); + } + else + { + ClipCursor(NULL); + } + + ShowCursor(bEnable ? FALSE : TRUE); + m_pRender->RenderEnable(RENDER_CENTER_CROSSHAIR, bEnable); +} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables mouselook. When mouselooking, the cursor is hidden +// and a crosshair is rendered in the center of the view. +// Input : bEnable - TRUE to enable, FALSE to disable mouselook. +//----------------------------------------------------------------------------- +//void CMapView3D::EnableMouseLook(bool bEnable) +//{ +// if (m_bMouseLook != bEnable) +// { +// CMapDoc *pDoc = GetDocument(); +// if (pDoc != NULL) +// { +// EnableCrosshair(bEnable); +// m_bMouseLook = bEnable; +// } +// } +//} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables mouselook. When mouselooking, the cursor is hidden +// and a crosshair is rendered in the center of the view. +//----------------------------------------------------------------------------- +void CMapView3D::EnableMouseLook(bool bEnable) +{ + if (m_bMouseLook != bEnable) + { + if (!(m_bStrafing || m_bRotating)) + { + EnableCrosshair(bEnable); + } + + m_bMouseLook = bEnable; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables camera rotating. When rotating, the cursor is hidden +// and a crosshair is rendered in the center of the view. +//----------------------------------------------------------------------------- +void CMapView3D::EnableRotating(bool bEnable) +{ + if (m_bRotating != bEnable) + { + if (!(m_bStrafing || m_bMouseLook)) + { + EnableCrosshair(bEnable); + } + + m_bRotating = bEnable; + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Enables or disables camera strafing. When strafing, the cursor is hidden +// and a crosshair is rendered in the center of the view. +//----------------------------------------------------------------------------- +void CMapView3D::EnableStrafing(bool bEnable) +{ + if (m_bStrafing != bEnable) + { + if (!(m_bMouseLook || m_bRotating)) + { + EnableCrosshair(bEnable); + } + + m_bStrafing = bEnable; + } +} + +//----------------------------------------------------------------------------- +// Purpose: Actually renders the 3D view. Called from the frame loop and from +// some mouse messages when timely updating is important. +//----------------------------------------------------------------------------- +void CMapView3D::Render(void) +{ + if ( m_pRender != NULL ) + { + m_pRender->Render(); + } + + if (m_pwndTitle != NULL) + { + m_pwndTitle->BringWindowToTop(); + m_pwndTitle->Invalidate(); + m_pwndTitle->UpdateWindow(); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: +// Input : *pObject - +//----------------------------------------------------------------------------- +void CMapView3D::RenderPreloadObject(CMapAtom *pObject) +{ + if ((pObject != NULL) && (m_pRender != NULL)) + { + pObject->RenderPreload(m_pRender, false); + } +} + + +//----------------------------------------------------------------------------- +// Release all video memory. +//----------------------------------------------------------------------------- +void CMapView3D::ReleaseVideoMemory(void) +{ + m_pRender->UncacheAllTextures(); +} + + +//----------------------------------------------------------------------------- +// Purpose: Moves the camera forward by flDistance units. Negative units move back. +//----------------------------------------------------------------------------- +void CMapView3D::MoveForward(float flDistance) +{ + if (m_pCamera != NULL) + { + m_pCamera->MoveForward(flDistance); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Moves the camera up by flDistance units. Negative units move down. +//----------------------------------------------------------------------------- +void CMapView3D::MoveUp(float flDistance) +{ + if (m_pCamera != NULL) + { + m_pCamera->MoveUp(flDistance); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Moves the camera right by flDistance units. Negative units move left. +//----------------------------------------------------------------------------- +void CMapView3D::MoveRight(float flDistance) +{ + if (m_pCamera != NULL) + { + m_pCamera->MoveRight(flDistance); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Pitches the camera forward by flDegrees degrees. Negative units pitch back. +//----------------------------------------------------------------------------- +void CMapView3D::Pitch(float flDegrees) +{ + if (m_pCamera != NULL) + { + m_pCamera->Pitch(flDegrees); + } +} + + +//----------------------------------------------------------------------------- +// Purpose: Yaws the camera left by flDegrees degrees. Negative units yaw right. +//----------------------------------------------------------------------------- +void CMapView3D::Yaw(float flDegrees) +{ + if (m_pCamera != NULL) + { + m_pCamera->Yaw(flDegrees); + } +} + + + +void CMapView3D::WorldToClient(Vector2D &vClient, const Vector &vWorld) +{ + m_pCamera->WorldToView( vWorld, vClient ); +} + +void CMapView3D::ClientToWorld(Vector &vWorld, const Vector2D &vClient) +{ + m_pCamera->ViewToWorld( vClient, vWorld ); +} + +void CMapView3D::SetCursor( vgui::HCursor hCursor ) +{ + // translate VGUI -> GDI cursors + switch( hCursor ) + { + case vgui::dc_arrow : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); break; + case vgui::dc_sizenwse : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENWSE)); break; + case vgui::dc_sizenesw : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENESW)); break; + case vgui::dc_sizewe : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEWE)); break; + case vgui::dc_sizens : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZENS)); break; + case vgui::dc_sizeall : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_SIZEALL)); break; + case vgui::dc_crosshair : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_CROSS)); break; + default : ::SetCursor(AfxGetApp()->LoadStandardCursor(IDC_ARROW)); break; + } +} + + +LRESULT CMapView3D::WindowProc( UINT message, WPARAM wParam, LPARAM lParam ) +{ + switch ( message ) + { + case WM_KILLFOCUS: + m_Keyboard.ClearKeyStates(); +// Msg( mwStatus, "debug: lost focus, clearing key states\n"); + break; + } + + return CView::WindowProc( message, wParam, lParam ) ; +}
\ No newline at end of file |