Counter Strike : Global Offensive Source Code
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.

763 lines
19 KiB

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Rendering and mouse handling in the 2D view.
  4. //
  5. //===========================================================================//
  6. #include "stdafx.h"
  7. #include "hammer.h"
  8. #include "MapView2D.h"
  9. #include "MapView3D.h"
  10. #include "MapDoc.h"
  11. #include "Render2D.h"
  12. #include "ToolManager.h"
  13. #include "History.h"
  14. #include "TitleWnd.h"
  15. #include "mainfrm.h"
  16. #include "MapSolid.h"
  17. #include "ToolMorph.h" // FIXME: remove
  18. #include "MapWorld.h"
  19. #include "camera.h"
  20. #include "Manifest.h"
  21. #include "MapInstance.h"
  22. #include "Options.h"
  23. #include "..\FoW\FoW.h"
  24. // memdbgon must be the last include file in a .cpp file!!!
  25. #include <tier0/memdbgon.h>
  26. extern bool g_bUpdateBones2D;
  27. static DrawType_t __eNextViewType = VIEW2D_XY;
  28. IMPLEMENT_DYNCREATE(CMapView2D, CMapView2DBase)
  29. BEGIN_MESSAGE_MAP(CMapView2D, CMapView2DBase)
  30. //{{AFX_MSG_MAP(CMapView2D)
  31. ON_WM_KEYDOWN()
  32. ON_COMMAND(ID_VIEW_2DXY, OnView2dxy)
  33. ON_COMMAND(ID_VIEW_2DYZ, OnView2dyz)
  34. ON_COMMAND(ID_VIEW_2DXZ, OnView2dxz)
  35. ON_COMMAND_EX(ID_TOOLS_ALIGNTOP, OnToolsAlign)
  36. ON_COMMAND_EX(ID_TOOLS_ALIGNBOTTOM, OnToolsAlign)
  37. ON_COMMAND_EX(ID_TOOLS_ALIGNLEFT, OnToolsAlign)
  38. ON_COMMAND_EX(ID_TOOLS_ALIGNRIGHT, OnToolsAlign)
  39. ON_COMMAND_EX(ID_FLIP_HORIZONTAL, OnFlip)
  40. ON_COMMAND_EX(ID_FLIP_VERTICAL, OnFlip)
  41. ON_UPDATE_COMMAND_UI(ID_FLIP_HORIZONTAL, OnUpdateEditSelection)
  42. ON_UPDATE_COMMAND_UI(ID_FLIP_VERTICAL, OnUpdateEditSelection)
  43. ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNTOP, OnUpdateEditSelection)
  44. ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNBOTTOM, OnUpdateEditSelection)
  45. ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNLEFT, OnUpdateEditSelection)
  46. ON_UPDATE_COMMAND_UI(ID_TOOLS_ALIGNRIGHT, OnUpdateEditSelection)
  47. //}}AFX_MSG_MAP
  48. END_MESSAGE_MAP()
  49. //-----------------------------------------------------------------------------
  50. // Purpose: Allows for iteration of draw types in order.
  51. // Input : eDrawType - Current draw type.
  52. // Output : Returns the next draw type in the list: XY, YZ, XZ. List wraps.
  53. //-----------------------------------------------------------------------------
  54. static DrawType_t NextDrawType(DrawType_t eDrawType)
  55. {
  56. if (eDrawType == VIEW2D_XY)
  57. {
  58. return(VIEW2D_YZ);
  59. }
  60. if (eDrawType == VIEW2D_YZ)
  61. {
  62. return(VIEW2D_XZ);
  63. }
  64. return(VIEW2D_XY);
  65. }
  66. //-----------------------------------------------------------------------------
  67. // Purpose: Allows for iteration of draw types in reverse order.
  68. // Input : eDrawType - Current draw type.
  69. // Output : Returns the previous draw type in the list: XY, YZ, XZ. List wraps.
  70. //-----------------------------------------------------------------------------
  71. static DrawType_t PrevDrawType(DrawType_t eDrawType)
  72. {
  73. if (eDrawType == VIEW2D_XY)
  74. {
  75. return(VIEW2D_XZ);
  76. }
  77. if (eDrawType == VIEW2D_YZ)
  78. {
  79. return(VIEW2D_XY);
  80. }
  81. return(VIEW2D_YZ);
  82. }
  83. //-----------------------------------------------------------------------------
  84. // Purpose: Constructor. Initializes data members.
  85. // ---------------------------------------------------------------------------
  86. CMapView2D::CMapView2D(void)
  87. {
  88. //
  89. // Create next 2d view type.
  90. //
  91. __eNextViewType = NextDrawType(__eNextViewType);
  92. SetDrawType(__eNextViewType);
  93. m_bUpdateRenderObjects = true;
  94. m_bLastActiveView = false;
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose: Destructor. Frees dynamically allocated resources.
  98. //-----------------------------------------------------------------------------
  99. CMapView2D::~CMapView2D(void)
  100. {
  101. if ( GetMapDoc() )
  102. {
  103. GetMapDoc()->RemoveMRU(this);
  104. }
  105. }
  106. //-----------------------------------------------------------------------------
  107. // Purpose: First-time initialization of this view.
  108. //-----------------------------------------------------------------------------
  109. void CMapView2D::OnInitialUpdate(void)
  110. {
  111. // NOTE: This must occur becore OnInitialUpdate
  112. // Creates the title window
  113. CreateTitleWindow();
  114. // NOTE: This must occur becore OnInitialUpdate
  115. // Other initialization.
  116. SetDrawType( GetDrawType() );
  117. CMapView2DBase::OnInitialUpdate();
  118. // Add to doc's MRU list
  119. CMapDoc *pDoc = GetMapDoc();
  120. pDoc->SetMRU(this);
  121. }
  122. //-----------------------------------------------------------------------------
  123. // Purpose:
  124. // Input : *pRender -
  125. //-----------------------------------------------------------------------------
  126. void CMapView2D::DrawPointFile( CRender2D *pRender )
  127. {
  128. pRender->SetDrawColor( 255,0,0 );
  129. int nPFPoints = GetMapDoc()->m_PFPoints.Count();
  130. Vector* pPFPoints = GetMapDoc()->m_PFPoints.Base();
  131. pRender->MoveTo( pPFPoints[0] );
  132. for(int i = 1; i < nPFPoints; i++)
  133. {
  134. pRender->DrawLineTo( pPFPoints[i] );
  135. }
  136. }
  137. //-----------------------------------------------------------------------------
  138. // Called when the base class wants the render lists to be recomputed
  139. //-----------------------------------------------------------------------------
  140. void CMapView2D::OnRenderListDirty()
  141. {
  142. m_bUpdateRenderObjects = true;
  143. }
  144. //-----------------------------------------------------------------------------
  145. // Purpose: Sorts the object to be rendered into one of two groups: normal objects
  146. // and selected objects, so that selected objects can be rendered last.
  147. // Input : pObject -
  148. // pRenderList -
  149. // Output : Returns TRUE on success, FALSE on failure.
  150. //-----------------------------------------------------------------------------
  151. void CMapView2D::AddToRenderLists(CMapClass *pObject)
  152. {
  153. if ( !pObject->IsVisible() )
  154. return;
  155. // Don't render groups, render their children instead.
  156. if ( !pObject->IsGroup() )
  157. {
  158. if ( !pObject->IsVisible2D() )
  159. return;
  160. Vector vecMins, vecMaxs;
  161. pObject->GetCullBox( vecMins, vecMaxs );
  162. if ( IsValidBox( vecMins, vecMaxs ) )
  163. {
  164. // Make sure the object is in the update region.
  165. if ( !IsInClientView(vecMins, vecMaxs) )
  166. return;
  167. }
  168. m_RenderList.AddToTail(pObject);
  169. }
  170. // Recurse into children and add them.
  171. const CMapObjectList *pChildren = pObject->GetChildren();
  172. FOR_EACH_OBJ( *pChildren, pos )
  173. {
  174. AddToRenderLists((CUtlReference< CMapClass >)pChildren->Element(pos));
  175. }
  176. }
  177. //-----------------------------------------------------------------------------
  178. // Purpose: horribly inefficient rendering mechanism for FoW. Demonstration purposes only!
  179. //-----------------------------------------------------------------------------
  180. void CMapView2D::RenderFoW( void )
  181. {
  182. CRender2D *pRender = GetRender();
  183. CFoW *pFoW = GetMapDoc()->GetFoW();
  184. Vector MinCoord, MaxCoord, MinDrawCoord, MaxDrawCoord;
  185. Vector2D DrawMins, DrawMaxs;
  186. int GridSize = pFoW->GetHorizontalGridSize();
  187. int MidPoint = GridSize / 2;
  188. Color color;
  189. pFoW->GetSize( MinCoord, MaxCoord );
  190. MinDrawCoord.z = MaxDrawCoord.z = 0;
  191. // pFoW->SnapCoordsToGrid( m_ViewMin, MinCoord, true );
  192. // pFoW->SnapCoordsToGrid( m_ViewMax, MaxCoord, false );
  193. pRender->PushRenderMode( RENDER_MODE_FLAT_NOZ );
  194. bool bPopMode = pRender->BeginClientSpace();
  195. for( int x = MinCoord.x; x < MaxCoord.x; x += GridSize )
  196. {
  197. MinDrawCoord.x = x;
  198. MaxDrawCoord.x = x + GridSize - 1;
  199. for( int y = MinCoord.y; y < MaxCoord.y; y += GridSize )
  200. {
  201. float Degree = pFoW->LookupVisibilityDegree( x + MidPoint, y + MidPoint, 0 );
  202. Degree = ( ( Degree * 0.25f ) + 0.0f ) * 255;
  203. if ( Degree >= 0.95f )
  204. {
  205. continue;
  206. }
  207. color.SetColor( 255, 0, 255, Degree );
  208. pRender->SetDrawColor( color );
  209. MaxDrawCoord.y = y;
  210. MinDrawCoord.y = y + GridSize - 1;
  211. pRender->TransformPoint( DrawMins, MinDrawCoord );
  212. pRender->TransformPoint( DrawMaxs, MaxDrawCoord );
  213. pRender->DrawFilledRect( DrawMins, DrawMaxs, ( byte * )&color, false );
  214. }
  215. }
  216. color.SetColor( 255, 255, 255, 255 );
  217. pRender->SetDrawColor( color );
  218. if ( bPopMode )
  219. {
  220. pRender->EndClientSpace();
  221. }
  222. pRender->PopRenderMode();
  223. }
  224. //-----------------------------------------------------------------------------
  225. // Purpose:
  226. // Input : rectUpdate -
  227. //-----------------------------------------------------------------------------
  228. void CMapView2D::Render()
  229. {
  230. // When in Foundry mode, the engine's vgui loop can cause Hammer's vgui windows to want to be drawn and we don't want that.
  231. // In any case, don't draw unless we're inside CVGuiWnd::DrawVGuiPanel or else windows and viewports will be all wrong.
  232. if ( !m_bIsDrawing )
  233. return;
  234. CMapDoc *pDoc = GetMapDoc();
  235. CMapWorld *pWorld = pDoc->GetMapWorld();
  236. CManifest *pManifest = pDoc->GetManifest();
  237. GetRender()->StartRenderFrame( false );
  238. if ( pManifest )
  239. {
  240. pWorld = pManifest->GetManifestWorld();
  241. }
  242. if ( Options.general.bRadiusCulling )
  243. {
  244. DrawCullingCircleHelper2D( GetRender() );
  245. }
  246. // Draw grid if enabled.
  247. if (pDoc->m_bShowGrid)
  248. {
  249. DrawGrid( GetRender(), axHorz, axVert, 0 );
  250. }
  251. //
  252. // Draw the world if we have one.
  253. //
  254. if (pWorld == NULL)
  255. return;
  256. // Traverse the entire world, sorting visible elements into two arrays:
  257. // Normal objects and selected objects, so that we can render the selected
  258. // objects last.
  259. //
  260. if ( m_bUpdateRenderObjects )
  261. {
  262. m_RenderList.RemoveAll();
  263. // fill render lists with visible objects
  264. AddToRenderLists( pWorld );
  265. g_bUpdateBones2D = true;
  266. }
  267. //
  268. // Render normal (nonselected) objects first
  269. //
  270. GetRender()->PrepareInstanceStencil();
  271. CUtlVector<CMapClass *> selectedObjects;
  272. CUtlVector<CMapClass *> helperObjects;
  273. for (int i = 0; i < m_RenderList.Count(); i++)
  274. {
  275. CMapClass *pObject = m_RenderList[i];
  276. if ( pObject->IsSelected() )
  277. {
  278. // render later
  279. if ( pObject->GetToolObject(0,false) )
  280. {
  281. helperObjects.AddToTail( pObject );
  282. }
  283. else
  284. {
  285. selectedObjects.AddToTail( pObject );
  286. }
  287. }
  288. else
  289. {
  290. // render now
  291. pObject->Render2D( GetRender() );
  292. }
  293. }
  294. //
  295. // Render selected objects in second batch, so they overdraw normal object
  296. //
  297. for (int i = 0; i < selectedObjects.Count(); i++)
  298. {
  299. selectedObjects[i]->Render2D( GetRender() );
  300. }
  301. GetRender()->DrawInstanceStencil();
  302. if ( pDoc->GetFoW() && m_eDrawType == VIEW2D_XY )
  303. { // only render the fog of war on the 2d top down view
  304. RenderFoW();
  305. }
  306. //
  307. // Draw pointfile if enabled.
  308. //
  309. if (pDoc->m_PFPoints.Count())
  310. {
  311. DrawPointFile( GetRender() );
  312. }
  313. pDoc->RenderDocument( GetRender() );
  314. m_bUpdateRenderObjects = false;
  315. g_bUpdateBones2D = false;
  316. // render all tools
  317. CBaseTool *pCurTool = m_pToolManager->GetActiveTool();
  318. // render active tool
  319. if ( pCurTool )
  320. {
  321. pCurTool->RenderTool2D( GetRender() );
  322. }
  323. // render map helpers at last
  324. for (int i = 0; i < helperObjects.Count(); i++)
  325. {
  326. helperObjects[i]->Render2D( GetRender() );
  327. }
  328. GetRender()->EndRenderFrame();
  329. }
  330. //-----------------------------------------------------------------------------
  331. // Purpose: this function will render an instance map at the specific offset and rotation
  332. // Input : pInstanceClass - the map class of the func_instance
  333. // pMapClass - the map class of the world spawn of the instance
  334. // InstanceOrigin - the translation offset
  335. // InstanceAngles - the axis rotation
  336. // Output : none
  337. //-----------------------------------------------------------------------------
  338. void CMapView2D::RenderInstance( CMapInstance *pInstanceClass, CMapClass *pMapClass, Vector &InstanceOrigin, QAngle &InstanceAngles )
  339. {
  340. if ( !pInstanceClass->IsInstanceVisible() )
  341. {
  342. return;
  343. }
  344. GetRender()->PushInstanceData( pInstanceClass, InstanceOrigin, InstanceAngles );
  345. RenderInstanceMapClass_r( pMapClass );
  346. GetRender()->PopInstanceData();
  347. }
  348. //-----------------------------------------------------------------------------
  349. // Purpose: this function will recursively render an instance and all of its children
  350. // Input : pObject - the object to be rendered
  351. // Output : none
  352. //-----------------------------------------------------------------------------
  353. void CMapView2D::RenderInstanceMapClass_r( CMapClass *pObject )
  354. {
  355. if ( !pObject->IsVisible() )
  356. {
  357. return;
  358. }
  359. // Don't render groups, render their children instead.
  360. if ( !pObject->IsGroup() )
  361. {
  362. if ( !pObject->IsVisible2D() )
  363. {
  364. return;
  365. }
  366. Vector vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs, vecOrigin;
  367. pObject->GetCullBox( vecMins, vecMaxs );
  368. GetRender()->TransformInstanceAABB( vecMins, vecMaxs, vecExpandedMins, vecExpandedMaxs );
  369. if ( IsValidBox( vecExpandedMins, vecExpandedMaxs ) )
  370. {
  371. // Make sure the object is in the update region.
  372. if ( !IsInClientView( vecExpandedMins, vecExpandedMaxs ) )
  373. {
  374. return;
  375. }
  376. }
  377. pObject->Render2D( GetRender() );
  378. }
  379. // Recurse into children and add them.
  380. const CMapObjectList *pChildren = pObject->GetChildren();
  381. FOR_EACH_OBJ( *pChildren, pos )
  382. {
  383. RenderInstanceMapClass_r((CUtlReference< CMapClass >)pChildren->Element(pos));
  384. }
  385. }
  386. //-----------------------------------------------------------------------------
  387. // Purpose:
  388. // Input : m_DrawType -
  389. // bForceUpdate -
  390. //-----------------------------------------------------------------------------
  391. void CMapView2D::SetDrawType(DrawType_t drawType)
  392. {
  393. Vector vOldView;
  394. // reset old third axis to selection center level
  395. m_pCamera->GetViewPoint( vOldView );
  396. CMapDoc *pDoc = GetMapDoc();
  397. if ( pDoc && !pDoc->GetSelection()->IsEmpty() )
  398. {
  399. Vector vCenter;
  400. pDoc->GetSelection()->GetBoundsCenter( vCenter );
  401. vOldView[axThird] = vCenter[axThird];
  402. }
  403. else
  404. {
  405. vOldView[axThird] = 0;
  406. }
  407. switch (drawType)
  408. {
  409. case VIEW2D_XY:
  410. SetAxes(AXIS_X, FALSE, AXIS_Y, TRUE);
  411. if ( HasTitleWnd() )
  412. {
  413. GetTitleWnd()->SetTitle("top (x/y)");
  414. }
  415. break;
  416. case VIEW2D_YZ:
  417. SetAxes(AXIS_Y, FALSE, AXIS_Z, TRUE);
  418. if ( HasTitleWnd() )
  419. {
  420. GetTitleWnd()->SetTitle("front (y/z)");
  421. }
  422. break;
  423. case VIEW2D_XZ:
  424. SetAxes(AXIS_X, FALSE, AXIS_Z, TRUE);
  425. if ( HasTitleWnd() )
  426. {
  427. GetTitleWnd()->SetTitle("side (x/z)");
  428. }
  429. break;
  430. }
  431. m_eDrawType = drawType;
  432. m_pCamera->SetViewPoint( vOldView );
  433. UpdateClientView();
  434. if (m_bLastActiveView && GetMapDoc())
  435. {
  436. GetMapDoc()->UpdateTitle(this);
  437. }
  438. }
  439. //-----------------------------------------------------------------------------
  440. // Purpose:
  441. //-----------------------------------------------------------------------------
  442. void CMapView2D::OnView2dxy(void)
  443. {
  444. SetDrawType(VIEW2D_XY);
  445. }
  446. //-----------------------------------------------------------------------------
  447. // Purpose:
  448. //-----------------------------------------------------------------------------
  449. void CMapView2D::OnView2dyz(void)
  450. {
  451. SetDrawType(VIEW2D_YZ);
  452. }
  453. //-----------------------------------------------------------------------------
  454. // Purpose:
  455. //-----------------------------------------------------------------------------
  456. void CMapView2D::OnView2dxz(void)
  457. {
  458. SetDrawType(VIEW2D_XZ);
  459. }
  460. //-----------------------------------------------------------------------------
  461. // Purpose:
  462. // Input : bActivate -
  463. // pActivateView -
  464. // pDeactiveView -
  465. //-----------------------------------------------------------------------------
  466. void CMapView2D::ActivateView(bool bActivate)
  467. {
  468. CMapView2DBase::ActivateView( bActivate );
  469. if ( bActivate )
  470. {
  471. CMapDoc *pDoc = GetMapDoc();
  472. pDoc->SetMRU(this);
  473. // tell doc to update title
  474. m_bLastActiveView = true;
  475. }
  476. else
  477. {
  478. m_bLastActiveView = false;
  479. }
  480. }
  481. //-----------------------------------------------------------------------------
  482. // Purpose:
  483. // Input : nID -
  484. // Output : Returns TRUE on success, FALSE on failure.
  485. //-----------------------------------------------------------------------------
  486. BOOL CMapView2D::OnToolsAlign(UINT nID)
  487. {
  488. CMapDoc *pDoc = GetMapDoc();
  489. CSelection *pSelection = pDoc->GetSelection();
  490. const CMapObjectList *pSelList = pSelection->GetList();
  491. GetHistory()->MarkUndoPosition(pSelList, "Align");
  492. GetHistory()->Keep(pSelList);
  493. // convert nID into the appropriate ID_TOOLS_ALIGNxxx define
  494. // taking into consideration the orientation of the axes
  495. if(nID == ID_TOOLS_ALIGNTOP && bInvertVert)
  496. nID = ID_TOOLS_ALIGNBOTTOM;
  497. else if(nID == ID_TOOLS_ALIGNBOTTOM && bInvertVert)
  498. nID = ID_TOOLS_ALIGNTOP;
  499. else if(nID == ID_TOOLS_ALIGNLEFT && bInvertHorz)
  500. nID = ID_TOOLS_ALIGNRIGHT;
  501. else if(nID == ID_TOOLS_ALIGNRIGHT && bInvertHorz)
  502. nID = ID_TOOLS_ALIGNLEFT;
  503. // use boundbox of selection - move all objects to match extreme
  504. // side of all the objects
  505. BoundBox box;
  506. pSelection->GetBounds(box.bmins, box.bmaxs);
  507. Vector ptMove( 0, 0, 0 );
  508. for (int i = 0; i < pSelList->Count(); i++)
  509. {
  510. CMapClass *pObject = (CUtlReference< CMapClass >)pSelList->Element(i);
  511. Vector vecMins;
  512. Vector vecMaxs;
  513. pObject->GetRender2DBox(vecMins, vecMaxs);
  514. // align top
  515. if (nID == ID_TOOLS_ALIGNTOP)
  516. {
  517. ptMove[axVert] = box.bmins[axVert] - vecMins[axVert];
  518. }
  519. else if (nID == ID_TOOLS_ALIGNBOTTOM)
  520. {
  521. ptMove[axVert] = box.bmaxs[axVert] - vecMaxs[axVert];
  522. }
  523. else if (nID == ID_TOOLS_ALIGNLEFT)
  524. {
  525. ptMove[axHorz] = box.bmins[axHorz] - vecMins[axHorz];
  526. }
  527. else if (nID == ID_TOOLS_ALIGNRIGHT)
  528. {
  529. ptMove[axHorz] = box.bmaxs[axHorz] - vecMaxs[axHorz];
  530. }
  531. pObject->TransMove(ptMove);
  532. }
  533. pDoc->SetModifiedFlag();
  534. return TRUE;
  535. }
  536. //-----------------------------------------------------------------------------
  537. // Purpose: Flips the selection horizontally or vertically (with respect to the
  538. // view orientation.
  539. // Input : nID -
  540. // Output : Returns TRUE on success, FALSE on failure.
  541. //-----------------------------------------------------------------------------
  542. BOOL CMapView2D::OnFlip(UINT nID)
  543. {
  544. CMapDoc *pDoc = GetMapDoc();
  545. CSelection *pSelection = pDoc->GetSelection();
  546. const CMapObjectList *pSelList = pSelection->GetList();
  547. if ( pSelection->IsEmpty() )
  548. {
  549. return TRUE; // no selection
  550. }
  551. // flip objects from center of selection
  552. Vector ptRef, vScale(1,1,1);
  553. pSelection->GetBoundsCenter(ptRef);
  554. // never about this axis:
  555. if (nID == ID_FLIP_HORIZONTAL)
  556. {
  557. vScale[axHorz] = -1;
  558. }
  559. else if (nID == ID_FLIP_VERTICAL)
  560. {
  561. vScale[axVert] = -1;
  562. }
  563. GetHistory()->MarkUndoPosition( pSelList, "Flip Objects");
  564. GetHistory()->Keep(pSelList);
  565. // do flip
  566. for (int i = 0; i < pSelList->Count(); i++)
  567. {
  568. CMapClass *pObject = (CUtlReference< CMapClass >)pSelList->Element(i);
  569. pObject->TransScale(ptRef,vScale);
  570. }
  571. pDoc->SetModifiedFlag();
  572. return TRUE;
  573. }
  574. //-----------------------------------------------------------------------------
  575. // Purpose: Manages the state of the Copy menu item.
  576. //-----------------------------------------------------------------------------
  577. void CMapView2D::OnUpdateEditSelection(CCmdUI *pCmdUI)
  578. {
  579. pCmdUI->Enable((!GetMapDoc()->GetSelection()->IsEmpty()) &&
  580. (m_pToolManager->GetActiveToolID() != TOOL_FACEEDIT_MATERIAL) &&
  581. !GetMainWnd()->IsShellSessionActive());
  582. }
  583. void CMapView2D::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
  584. {
  585. if (nChar == VK_TAB)
  586. {
  587. // swicth to next draw type
  588. SetDrawType( NextDrawType( m_eDrawType ) );
  589. return;
  590. }
  591. CMapView2DBase::OnKeyDown( nChar, nRepCnt, nFlags );
  592. }
  593. void CMapView2D::DrawCullingCircleHelper2D( CRender2D *pRender )
  594. {
  595. CMapDoc *pDoc = GetMapDoc();
  596. POSITION viewpos = pDoc->GetFirstViewPosition();
  597. while ( viewpos )
  598. {
  599. CMapView3D *pView = dynamic_cast<CMapView3D*>( pDoc->GetNextView( viewpos ) );
  600. if ( pView )
  601. {
  602. CCamera *pCamera = pView->GetCamera();
  603. Vector cameraPos;
  604. pCamera->GetViewPoint( cameraPos );
  605. int iClipDist = (int)pCamera->GetFarClip();
  606. pRender->SetDrawColor( 255, 0, 0 );
  607. pRender->DrawCircle( cameraPos, iClipDist );
  608. }
  609. }
  610. }