Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

816 lines
20 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "stdafx.h"
  8. #include "ToolCamera.h"
  9. #include "SaveInfo.h"
  10. #include "MainFrm.h" // dvs: remove?
  11. #include "MapDefs.h"
  12. #include "MapDoc.h"
  13. #include "MapView2D.h"
  14. #include "MapView3D.h"
  15. #include "Options.h"
  16. #include "Render2D.h"
  17. #include "StatusBarIDs.h" // dvs: remove
  18. #include "ToolManager.h"
  19. #include "hammer_mathlib.h"
  20. #include "vgui/Cursor.h"
  21. #include "Selection.h"
  22. // memdbgon must be the last include file in a .cpp file!!!
  23. #include <tier0/memdbgon.h>
  24. #pragma warning(disable:4244)
  25. //-----------------------------------------------------------------------------
  26. // Purpose:
  27. //-----------------------------------------------------------------------------
  28. Camera3D::Camera3D(void)
  29. {
  30. Cameras.EnsureCapacity(16);
  31. SetEmpty();
  32. }
  33. //-----------------------------------------------------------------------------
  34. // Purpose: Returns true if we are dragging a camera, false if not. // dvs: rename
  35. //-----------------------------------------------------------------------------
  36. bool Camera3D::IsEmpty(void)
  37. {
  38. return (Cameras.Count() == 0);
  39. }
  40. //-----------------------------------------------------------------------------
  41. // Purpose:
  42. //-----------------------------------------------------------------------------
  43. void Camera3D::SetEmpty(void)
  44. {
  45. Cameras.RemoveAll();
  46. m_iActiveCamera = -1;
  47. }
  48. //-----------------------------------------------------------------------------
  49. // Purpose:
  50. // Input : pt -
  51. // BOOL -
  52. // Output : int
  53. //-----------------------------------------------------------------------------
  54. int Camera3D::HitTest(CMapView *pView, const Vector2D &ptClient, bool bTestHandles)
  55. {
  56. for(int i = 0; i < Cameras.Count(); i++)
  57. {
  58. for ( int j=0; j<2; j++ )
  59. {
  60. if( HitRect( pView, ptClient, Cameras[i].position[j], HANDLE_RADIUS ) )
  61. {
  62. return MAKELONG(i+1, j);
  63. }
  64. }
  65. }
  66. return FALSE;
  67. }
  68. //-----------------------------------------------------------------------------
  69. // Purpose: Get rid of extra cameras if we have too many.
  70. //-----------------------------------------------------------------------------
  71. void Camera3D::EnsureMaxCameras()
  72. {
  73. int nMax = max( Options.general.nMaxCameras, 1 );
  74. int nToRemove = Cameras.Count() - nMax;
  75. if ( nToRemove > 0 )
  76. {
  77. m_iActiveCamera = max( m_iActiveCamera - nToRemove, 0 );
  78. while ( nToRemove-- )
  79. Cameras.Remove( 0 );
  80. }
  81. }
  82. //-----------------------------------------------------------------------------
  83. // Purpose:
  84. // Input : bSave -
  85. //-----------------------------------------------------------------------------
  86. void Camera3D::FinishTranslation(bool bSave)
  87. {
  88. if (bSave)
  89. {
  90. if ( m_iActiveCamera == Cameras.Count() )
  91. {
  92. Cameras.AddToTail();
  93. EnsureMaxCameras();
  94. }
  95. Cameras[m_iActiveCamera] = m_MoveCamera;
  96. }
  97. Tool3D::FinishTranslation(bSave);
  98. }
  99. //-----------------------------------------------------------------------------
  100. // Purpose:
  101. // Input : pt -
  102. // uFlags -
  103. // CSize& -
  104. // Output : Returns TRUE on success, FALSE on failure.
  105. //-----------------------------------------------------------------------------
  106. bool Camera3D::UpdateTranslation(const Vector &vUpdate, UINT uFlags)
  107. {
  108. Vector vCamDelta = m_MoveCamera.position[1] - m_MoveCamera.position[0];
  109. Vector vNewPos = m_vOrgPos + vUpdate;
  110. // snap point if need be
  111. if ( uFlags & constrainSnap )
  112. m_pDocument->Snap( vNewPos, uFlags );
  113. m_MoveCamera.position[m_nMovePositionIndex] = vNewPos;
  114. if(uFlags & constrainMoveAll)
  115. {
  116. m_MoveCamera.position[(m_nMovePositionIndex+1)%2] = vNewPos + vCamDelta;
  117. }
  118. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  119. return true;
  120. }
  121. //-----------------------------------------------------------------------------
  122. // Purpose:
  123. // Input : pCamPos -
  124. // iCamera -
  125. //-----------------------------------------------------------------------------
  126. void Camera3D::GetCameraPos(Vector &vViewPos, Vector &vLookAt)
  127. {
  128. if(!inrange(m_iActiveCamera, 0, Cameras.Count()))
  129. {
  130. vViewPos.Init();
  131. vLookAt.Init();
  132. return;
  133. }
  134. vViewPos = Cameras[m_iActiveCamera].position[0];
  135. vLookAt = Cameras[m_iActiveCamera].position[1];
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Purpose:
  139. // Input : pCamPos -
  140. // iCamera -
  141. //-----------------------------------------------------------------------------
  142. void Camera3D::AddCamera(CAMSTRUCT &camera)
  143. {
  144. Cameras.AddToTail( camera );
  145. EnsureMaxCameras();
  146. }
  147. //-----------------------------------------------------------------------------
  148. // Purpose:
  149. // Input : pRender -
  150. //-----------------------------------------------------------------------------
  151. void Camera3D::RenderTool2D(CRender2D *pRender)
  152. {
  153. for (int i = 0; i < Cameras.Count(); i++)
  154. {
  155. CAMSTRUCT *pDrawCam = &Cameras[i];
  156. if (IsTranslating() && (i == m_iActiveCamera))
  157. {
  158. pDrawCam = &m_MoveCamera;
  159. }
  160. //
  161. // Draw the line between.
  162. //
  163. if (i == m_iActiveCamera)
  164. {
  165. pRender->SetDrawColor( 255, 0, 0 );
  166. }
  167. else
  168. {
  169. pRender->SetDrawColor( 0, 255, 255 );
  170. }
  171. pRender->DrawLine( pDrawCam->position[MovePos], pDrawCam->position[MoveLook] );
  172. //
  173. // Draw camera handle.
  174. //
  175. pRender->SetHandleStyle(HANDLE_RADIUS, CRender::HANDLE_CIRCLE );
  176. pRender->SetHandleColor( 0, 255, 255 );
  177. pRender->DrawHandle( pDrawCam->position[MovePos] );
  178. }
  179. }
  180. //-----------------------------------------------------------------------------
  181. // Purpose: Handles key values being read from the MAP file.
  182. // Input : szKey - Key being loaded.
  183. // szValue - Value of the key being loaded.
  184. // pCam - Camera structure to place the values into.
  185. // Output : Returns ChunkFile_Ok to indicate success.
  186. //-----------------------------------------------------------------------------
  187. ChunkFileResult_t Camera3D::LoadCameraKeyCallback(const char *szKey, const char *szValue, CAMSTRUCT *pCam)
  188. {
  189. if (!stricmp(szKey, "look"))
  190. {
  191. CChunkFile::ReadKeyValueVector3(szValue, pCam->position[MoveLook]);
  192. }
  193. else if (!stricmp(szKey, "position"))
  194. {
  195. CChunkFile::ReadKeyValueVector3(szValue, pCam->position[MovePos]);
  196. }
  197. return(ChunkFile_Ok);
  198. }
  199. //-----------------------------------------------------------------------------
  200. // Purpose: Handles key values being read from the MAP file.
  201. // Input : szKey - Key being loaded.
  202. // szValue - Value of the key being loaded.
  203. // pCam - Camera structure to place the values into.
  204. // Output : Returns ChunkFile_Ok to indicate success.
  205. //-----------------------------------------------------------------------------
  206. ChunkFileResult_t Camera3D::LoadCamerasKeyCallback(const char *szKey, const char *szValue, Camera3D *pCameras)
  207. {
  208. if (!stricmp(szKey, "activecamera"))
  209. {
  210. pCameras->m_iActiveCamera = atoi(szValue);
  211. }
  212. return(ChunkFile_Ok);
  213. }
  214. //-----------------------------------------------------------------------------
  215. // Purpose:
  216. // Input : *pLoadInfo -
  217. // *pSolid -
  218. // Output : ChunkFileResult_t
  219. //-----------------------------------------------------------------------------
  220. ChunkFileResult_t Camera3D::LoadCameraCallback(CChunkFile *pFile, Camera3D *pCameras)
  221. {
  222. CAMSTRUCT Cam;
  223. memset(&Cam, 0, sizeof(Cam));
  224. ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadCameraKeyCallback, &Cam);
  225. if (eResult == ChunkFile_Ok)
  226. {
  227. pCameras->AddCamera( Cam );
  228. }
  229. return(eResult);
  230. }
  231. //-----------------------------------------------------------------------------
  232. // Purpose:
  233. // Input : *pFile -
  234. // Output : ChunkFileResult_t
  235. //-----------------------------------------------------------------------------
  236. ChunkFileResult_t Camera3D::LoadVMF(CChunkFile *pFile)
  237. {
  238. //
  239. // Set up handlers for the subchunks that we are interested in.
  240. //
  241. CChunkHandlerMap Handlers;
  242. Handlers.AddHandler("camera", (ChunkHandler_t)LoadCameraCallback, this);
  243. pFile->PushHandlers(&Handlers);
  244. ChunkFileResult_t eResult = pFile->ReadChunk((KeyHandler_t)LoadCamerasKeyCallback, this);
  245. pFile->PopHandlers();
  246. if (eResult == ChunkFile_Ok)
  247. {
  248. //
  249. // Make sure the active camera is legal.
  250. //
  251. if (Cameras.Count() == 0)
  252. {
  253. m_iActiveCamera = -1;
  254. }
  255. else if (!inrange(m_iActiveCamera, 0, Cameras.Count()))
  256. {
  257. m_iActiveCamera = 0;
  258. }
  259. }
  260. return(eResult);
  261. }
  262. //-----------------------------------------------------------------------------
  263. // Purpose:
  264. // Input : &dir -
  265. // &pos -
  266. //-----------------------------------------------------------------------------
  267. void Camera3D::UpdateActiveCamera(Vector &vViewPos, Vector &vDir)
  268. {
  269. if(!inrange(m_iActiveCamera, 0, Cameras.Count()))
  270. return;
  271. Vector& camPos = Cameras[m_iActiveCamera].position[MovePos];
  272. Vector& lookPos = Cameras[m_iActiveCamera].position[MoveLook];
  273. // get current length
  274. Vector delta;
  275. for(int i = 0; i < 3; i++)
  276. delta[i] = camPos[i] - lookPos[i];
  277. float length = VectorLength(delta);
  278. if ( length < 1 )
  279. length = 1;
  280. camPos = vViewPos;
  281. for(int i = 0; i < 3; i++)
  282. lookPos[i] = camPos[i] + vDir[i] * length;
  283. if ( IsActiveTool() )
  284. {
  285. if (Options.view2d.bCenteroncamera)
  286. {
  287. VIEW2DINFO vi;
  288. vi.wFlags = VI_CENTER;
  289. vi.ptCenter = vViewPos;
  290. m_pDocument->SetView2dInfo(vi);
  291. }
  292. m_pDocument->UpdateAllViews( MAPVIEW_UPDATE_TOOL );
  293. }
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Purpose:
  297. // Input : type -
  298. //-----------------------------------------------------------------------------
  299. void Camera3D::SetNextCamera(SNCTYPE type)
  300. {
  301. if(Cameras.Count()==0)
  302. {
  303. m_iActiveCamera = -1;
  304. return;
  305. }
  306. switch(type)
  307. {
  308. case sncNext:
  309. ++m_iActiveCamera;
  310. if(m_iActiveCamera >= Cameras.Count() )
  311. m_iActiveCamera = 0;
  312. break;
  313. case sncPrev:
  314. --m_iActiveCamera;
  315. if(m_iActiveCamera < 0)
  316. m_iActiveCamera = Cameras.Count()-1;
  317. break;
  318. case sncFirst:
  319. m_iActiveCamera = 0;
  320. break;
  321. }
  322. }
  323. //-----------------------------------------------------------------------------
  324. // Purpose:
  325. //-----------------------------------------------------------------------------
  326. void Camera3D::DeleteActiveCamera()
  327. {
  328. if(!inrange(m_iActiveCamera, 0, Cameras.Count()))
  329. return;
  330. Cameras.Remove(m_iActiveCamera);
  331. if(m_iActiveCamera >= Cameras.Count() )
  332. m_iActiveCamera = Cameras.Count()-1;
  333. }
  334. //-----------------------------------------------------------------------------
  335. // Purpose:
  336. // Input : file -
  337. // fIsStoring -
  338. //-----------------------------------------------------------------------------
  339. void Camera3D::SerializeRMF(std::fstream& file, BOOL fIsStoring)
  340. {
  341. float fVersion = 0.2f, fThisVersion;
  342. int nCameras = Cameras.Count();
  343. if(fIsStoring)
  344. {
  345. file.write((char*)&fVersion, sizeof(fVersion) );
  346. file.write((char*)&m_iActiveCamera, sizeof(m_iActiveCamera) );
  347. file.write((char*)&nCameras, sizeof(nCameras));
  348. for(int i = 0; i < nCameras; i++)
  349. {
  350. file.write((char*)&Cameras[i], sizeof(CAMSTRUCT));
  351. }
  352. }
  353. else
  354. {
  355. file.read((char*)&fThisVersion, sizeof(fThisVersion) );
  356. if(fThisVersion >= 0.2f)
  357. {
  358. file.read((char*)&m_iActiveCamera, sizeof(m_iActiveCamera));
  359. }
  360. file.read((char*)&nCameras, sizeof (nCameras) );
  361. Cameras.RemoveAll();
  362. Cameras.EnsureCapacity(nCameras);
  363. for(int i = 0; i < nCameras; i++)
  364. {
  365. CAMSTRUCT cam;
  366. file.read((char*)&cam, sizeof(CAMSTRUCT));
  367. Cameras.AddToTail( cam );
  368. }
  369. EnsureMaxCameras();
  370. Assert( Cameras.Count() == nCameras );
  371. }
  372. }
  373. //-----------------------------------------------------------------------------
  374. // Purpose:
  375. // Input : *pFile -
  376. // Output : ChunkFileResult_t
  377. //-----------------------------------------------------------------------------
  378. ChunkFileResult_t Camera3D::SaveVMF(CChunkFile *pFile, CSaveInfo *pSaveInfo)
  379. {
  380. ChunkFileResult_t eResult = pFile->BeginChunk( GetVMFChunkName() );
  381. if (eResult == ChunkFile_Ok)
  382. {
  383. eResult = pFile->WriteKeyValueInt("activecamera", m_iActiveCamera);
  384. }
  385. if (eResult == ChunkFile_Ok)
  386. {
  387. for (int i = 0; i < Cameras.Count(); i++)
  388. {
  389. eResult = pFile->BeginChunk("camera");
  390. if (eResult == ChunkFile_Ok)
  391. {
  392. eResult = pFile->WriteKeyValueVector3("position", Cameras[i].position[MovePos]);
  393. }
  394. if (eResult == ChunkFile_Ok)
  395. {
  396. eResult = pFile->WriteKeyValueVector3("look", Cameras[i].position[MoveLook]);
  397. }
  398. if (eResult == ChunkFile_Ok)
  399. {
  400. eResult = pFile->EndChunk();
  401. }
  402. if (eResult != ChunkFile_Ok)
  403. {
  404. break;
  405. }
  406. }
  407. }
  408. if (eResult == ChunkFile_Ok)
  409. {
  410. eResult = pFile->EndChunk();
  411. }
  412. return(eResult);
  413. }
  414. //-----------------------------------------------------------------------------
  415. // Purpose: Handles the key down event in the 2D view.
  416. // Input : Per CWnd::OnKeyDown.
  417. // Output : Returns true if the message was handled, false if not.
  418. //-----------------------------------------------------------------------------
  419. bool Camera3D::OnKeyDown2D(CMapView2D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
  420. {
  421. if (nChar == VK_DELETE || nChar == VK_NEXT || nChar == VK_PRIOR)
  422. {
  423. CMapDoc *pDoc = pView->GetMapDoc();
  424. if (nChar == VK_DELETE)
  425. {
  426. DeleteActiveCamera();
  427. }
  428. else if (nChar == VK_NEXT)
  429. {
  430. SetNextCamera(Camera3D::sncNext);
  431. }
  432. else
  433. {
  434. SetNextCamera(Camera3D::sncPrev);
  435. }
  436. Vector viewPos,lookAt;
  437. GetCameraPos( viewPos, lookAt );
  438. pDoc->UpdateAllCameras( &viewPos, &lookAt, NULL );
  439. return true;
  440. }
  441. else if (nChar == VK_ESCAPE)
  442. {
  443. OnEscape();
  444. return true;
  445. }
  446. return false;
  447. }
  448. //-----------------------------------------------------------------------------
  449. // Purpose: Handles the left mouse button down event in the 2D view.
  450. // Input : Per CWnd::OnLButtonDown.
  451. // Output : Returns true if the message was handled, false if not.
  452. //-----------------------------------------------------------------------------
  453. bool Camera3D::OnLMouseDown2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
  454. {
  455. CMapDoc *pDoc = pView->GetMapDoc();
  456. pView->SetCapture();
  457. //
  458. // If there are no cameras created yet or they are holding down
  459. // the SHIFT key, create a new camera now.
  460. //
  461. Vector vecWorld;
  462. pView->ClientToWorld( vecWorld, vPoint );
  463. if ( IsEmpty() || (nFlags & MK_SHIFT))
  464. {
  465. //
  466. // Build a point in world space to place the new camera.
  467. //
  468. if ( !pDoc->GetSelection()->IsEmpty() )
  469. {
  470. Vector vecCenter;
  471. pDoc->GetSelection()->GetBoundsCenter(vecCenter);
  472. vecWorld[pView->axThird] = vecCenter[pView->axThird];
  473. }
  474. else
  475. {
  476. vecWorld[pView->axThird] = COORD_NOTINIT;
  477. pDoc->GetBestVisiblePoint(vecWorld);
  478. }
  479. //
  480. // Create a new camera.
  481. //
  482. m_vOrgPos = vecWorld;
  483. m_MoveCamera.position[MovePos] = vecWorld;
  484. m_MoveCamera.position[MoveLook] = vecWorld;
  485. m_nMovePositionIndex = MoveLook;
  486. // set as active camera
  487. m_iActiveCamera = Cameras.AddToTail(m_MoveCamera);;
  488. EnsureMaxCameras();
  489. StartTranslation(pView, vPoint );
  490. }
  491. //
  492. // Otherwise, try to drag an existing camera handle.
  493. //
  494. else
  495. {
  496. int dwHit = HitTest( pView, vPoint );
  497. if ( dwHit )
  498. {
  499. m_iActiveCamera = LOWORD(dwHit)-1;
  500. m_MoveCamera = Cameras[m_iActiveCamera];
  501. m_nMovePositionIndex = HIWORD(dwHit);
  502. m_vOrgPos = m_MoveCamera.position[m_nMovePositionIndex];
  503. StartTranslation( pView, vPoint );
  504. }
  505. }
  506. return true;
  507. }
  508. //-----------------------------------------------------------------------------
  509. // Purpose: Handles the left mouse button up event in the 2D view.
  510. // Input : Per CWnd::OnLButtonUp.
  511. // Output : Returns true if the message was handled, false if not.
  512. //-----------------------------------------------------------------------------
  513. bool Camera3D::OnLMouseUp2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
  514. {
  515. ReleaseCapture();
  516. if (IsTranslating())
  517. {
  518. FinishTranslation(true);
  519. Vector viewPos, lookAt;
  520. GetCameraPos( viewPos, lookAt );
  521. m_pDocument->UpdateAllCameras( &viewPos, &lookAt, NULL );
  522. }
  523. m_pDocument->UpdateStatusbar();
  524. return true;
  525. }
  526. unsigned int Camera3D::GetConstraints(unsigned int nKeyFlags)
  527. {
  528. unsigned int uConstraints = Tool3D::GetConstraints( nKeyFlags );
  529. if(nKeyFlags & MK_CONTROL)
  530. {
  531. uConstraints |= constrainMoveAll;
  532. }
  533. return uConstraints;
  534. }
  535. //-----------------------------------------------------------------------------
  536. // Purpose: Handles the mouse move event in the 2D view.
  537. // Input : Per CWnd::OnMouseMove.
  538. // Output : Returns true if the message was handled, false if not.
  539. //-----------------------------------------------------------------------------
  540. bool Camera3D::OnMouseMove2D(CMapView2D *pView, UINT nFlags, const Vector2D &vPoint)
  541. {
  542. CMapDoc *pDoc = pView->GetMapDoc();
  543. if (!pDoc)
  544. {
  545. return true;
  546. }
  547. vgui::HCursor hCursor = vgui::dc_arrow;
  548. unsigned int uConstraints = GetConstraints( nFlags );
  549. // Make sure the point is visible.
  550. pView->ToolScrollToPoint( vPoint );
  551. //
  552. // Convert to world coords.
  553. //
  554. Vector vecWorld;
  555. pView->ClientToWorld(vecWorld, vPoint);
  556. //
  557. // Update status bar position display.
  558. //
  559. char szBuf[128];
  560. m_pDocument->Snap(vecWorld,uConstraints);
  561. sprintf(szBuf, " @%.0f, %.0f ", vecWorld[pView->axHorz], vecWorld[pView->axVert] );
  562. SetStatusText(SBI_COORDS, szBuf);
  563. if (IsTranslating())
  564. {
  565. Tool3D::UpdateTranslation(pView, vPoint, uConstraints );
  566. hCursor = vgui::dc_none;
  567. }
  568. else if ( !IsEmpty() )
  569. {
  570. //
  571. // If the cursor is on a handle, set it to a cross.
  572. //
  573. if ( HitTest( pView, vPoint, true) )
  574. {
  575. hCursor = vgui::dc_crosshair;
  576. }
  577. }
  578. if ( hCursor != vgui::dc_none )
  579. pView->SetCursor( hCursor );
  580. return true;
  581. }
  582. //-----------------------------------------------------------------------------
  583. // Purpose: Handles the left mouse button down event in the 3D view.
  584. // Input : Per CWnd::OnLButtonDown.
  585. // Output : Returns true if the message was handled, false if not.
  586. //-----------------------------------------------------------------------------
  587. bool Camera3D::OnLMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
  588. {
  589. pView->EnableRotating(true);
  590. return true;
  591. }
  592. //-----------------------------------------------------------------------------
  593. // Purpose: Handles the left mouse up down event in the 3D view.
  594. // Input : Per CWnd::OnLButtonUp.
  595. // Output : Returns true if the message was handled, false if not.
  596. //-----------------------------------------------------------------------------
  597. bool Camera3D::OnLMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
  598. {
  599. pView->EnableRotating(false);
  600. pView->UpdateCameraVariables();
  601. return true;
  602. }
  603. //-----------------------------------------------------------------------------
  604. // Purpose: Handles the right mouse button down event in the 3D view.
  605. // Input : Per CWnd::OnRButtonDown.
  606. // Output : Returns true if the message was handled, false if not.
  607. //-----------------------------------------------------------------------------
  608. bool Camera3D::OnRMouseDown3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
  609. {
  610. pView->EnableStrafing(true);
  611. return true;
  612. }
  613. //-----------------------------------------------------------------------------
  614. // Purpose: Handles the right mouse button up event in the 3D view.
  615. // Input : Per CWnd::OnRButtonUp.
  616. // Output : Returns true if the message was handled, false if not.
  617. //-----------------------------------------------------------------------------
  618. bool Camera3D::OnRMouseUp3D(CMapView3D *pView, UINT nFlags, const Vector2D &vPoint)
  619. {
  620. pView->EnableStrafing(false);
  621. pView->UpdateCameraVariables();
  622. return true;
  623. }
  624. //-----------------------------------------------------------------------------
  625. // Purpose: Handles the key down event in the 3D view.
  626. // Input : Per CWnd::OnKeyDown.
  627. // Output : Returns true if the message was handled, false if not.
  628. //-----------------------------------------------------------------------------
  629. bool Camera3D::OnKeyDown3D(CMapView3D *pView, UINT nChar, UINT nRepCnt, UINT nFlags)
  630. {
  631. if (nChar == VK_DELETE || nChar == VK_NEXT || nChar == VK_PRIOR)
  632. {
  633. CMapDoc *pDoc = pView->GetMapDoc();
  634. if (nChar == VK_DELETE)
  635. {
  636. DeleteActiveCamera();
  637. }
  638. else if (nChar == VK_NEXT)
  639. {
  640. SetNextCamera(Camera3D::sncNext);
  641. }
  642. else
  643. {
  644. SetNextCamera(Camera3D::sncPrev);
  645. }
  646. Vector viewPos, lookAt;
  647. GetCameraPos( viewPos, lookAt );
  648. pDoc->UpdateAllCameras( &viewPos, &lookAt, NULL );
  649. return true;
  650. }
  651. else if (nChar == VK_ESCAPE)
  652. {
  653. OnEscape();
  654. return true;
  655. }
  656. return false;
  657. }
  658. //-----------------------------------------------------------------------------
  659. // Purpose: Handles the escape key in the 2D or 3D views.
  660. //-----------------------------------------------------------------------------
  661. void Camera3D::OnEscape(void)
  662. {
  663. //
  664. // Stop using the camera tool.
  665. //
  666. m_pDocument->GetTools()->SetTool(TOOL_POINTER);
  667. }