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.

892 lines
21 KiB

  1. //--------------------------------------------------------------------------------------------------------
  2. //========= Copyright Valve Corporation, All rights reserved. ============//
  3. #include "cbase.h"
  4. #ifdef SERVER_USES_VGUI
  5. #include "NavUI.h"
  6. #include "filesystem.h"
  7. #include "tier0/icommandline.h"
  8. #include "vgui_gamedll_int.h"
  9. #include "ienginevgui.h"
  10. #include "IGameUIFuncs.h"
  11. #include "fmtstr.h"
  12. #include "NavMenu.h"
  13. #include <vgui_controls/MenuButton.h>
  14. #include "SelectionTool.h"
  15. #include "MeshTool.h"
  16. #include "AttributeTool.h"
  17. // memdbgon must be the last include file in a .cpp file!!!
  18. #include "tier0/memdbgon.h"
  19. using namespace vgui;
  20. class CNavUIBasePanel;
  21. class CNavUIToolPanel;
  22. extern IGameUIFuncs *gameuifuncs;
  23. //--------------------------------------------------------------------------------------------------------
  24. static CNavUIBasePanel *s_navUIPanel = NULL;
  25. CNavUIBasePanel *TheNavUI( void )
  26. {
  27. return s_navUIPanel;
  28. }
  29. //--------------------------------------------------------------------------------------------------------
  30. ConVar NavGUIRebuild( "nav_gui_rebuild", "0", FCVAR_CHEAT, "Rebuilds the nav ui windows from scratch every time they're opened" );
  31. //--------------------------------------------------------------------------------------------------------
  32. void CNavUIButton::LookupKey( void )
  33. {
  34. if ( m_hideKey == BUTTON_CODE_INVALID )
  35. m_hideKey = (gameuifuncs) ? gameuifuncs->GetButtonCodeForBind( "nav_gui" ) : BUTTON_CODE_INVALID;
  36. }
  37. //--------------------------------------------------------------------------------------------------------
  38. void CNavUIButton::OnKeyCodePressed( KeyCode code )
  39. {
  40. LookupKey();
  41. if ( code == m_hideKey )
  42. {
  43. m_hidePressedTimer.Start();
  44. return;
  45. }
  46. BaseClass::OnKeyCodePressed( code );
  47. }
  48. //--------------------------------------------------------------------------------------------------------
  49. void CNavUIButton::OnKeyCodeReleased( KeyCode code )
  50. {
  51. LookupKey();
  52. if ( code == m_hideKey )
  53. {
  54. if ( m_hidePressedTimer.HasStarted() && m_hidePressedTimer.GetElapsedTime() < 0.5f )
  55. {
  56. s_navUIPanel->ToggleVisibility();
  57. m_hidePressedTimer.Invalidate();
  58. }
  59. return;
  60. }
  61. BaseClass::OnKeyCodeReleased( code );
  62. }
  63. //--------------------------------------------------------------------------------------------------------
  64. void CNavUITextEntry::LookupKey( void )
  65. {
  66. if ( m_hideKey == BUTTON_CODE_INVALID )
  67. m_hideKey = (gameuifuncs) ? gameuifuncs->GetButtonCodeForBind( "nav_gui" ) : BUTTON_CODE_INVALID;
  68. }
  69. //--------------------------------------------------------------------------------------------------------
  70. void CNavUITextEntry::OnKeyCodePressed( KeyCode code )
  71. {
  72. LookupKey();
  73. if ( code == m_hideKey )
  74. {
  75. m_hidePressedTimer.Start();
  76. return;
  77. }
  78. BaseClass::OnKeyCodePressed( code );
  79. }
  80. //--------------------------------------------------------------------------------------------------------
  81. void CNavUITextEntry::OnKeyCodeReleased( KeyCode code )
  82. {
  83. LookupKey();
  84. if ( code == m_hideKey )
  85. {
  86. if ( m_hidePressedTimer.HasStarted() && m_hidePressedTimer.GetElapsedTime() < 0.5f )
  87. {
  88. s_navUIPanel->ToggleVisibility();
  89. m_hidePressedTimer.Invalidate();
  90. }
  91. return;
  92. }
  93. BaseClass::OnKeyCodeReleased( code );
  94. }
  95. //--------------------------------------------------------------------------------------------------------
  96. void CNavUIComboBox::LookupKey( void )
  97. {
  98. if ( m_hideKey == BUTTON_CODE_INVALID )
  99. m_hideKey = (gameuifuncs) ? gameuifuncs->GetButtonCodeForBind( "nav_gui" ) : BUTTON_CODE_INVALID;
  100. }
  101. //--------------------------------------------------------------------------------------------------------
  102. void CNavUIComboBox::OnKeyCodePressed( KeyCode code )
  103. {
  104. LookupKey();
  105. if ( code == m_hideKey )
  106. {
  107. m_hidePressedTimer.Start();
  108. return;
  109. }
  110. BaseClass::OnKeyCodePressed( code );
  111. }
  112. //--------------------------------------------------------------------------------------------------------
  113. void CNavUIComboBox::OnKeyCodeReleased( KeyCode code )
  114. {
  115. LookupKey();
  116. if ( code == m_hideKey )
  117. {
  118. if ( m_hidePressedTimer.HasStarted() && m_hidePressedTimer.GetElapsedTime() < 0.5f )
  119. {
  120. s_navUIPanel->ToggleVisibility();
  121. m_hidePressedTimer.Invalidate();
  122. }
  123. return;
  124. }
  125. BaseClass::OnKeyCodeReleased( code );
  126. }
  127. //--------------------------------------------------------------------------------------------------------
  128. void CNavUICheckButton::LookupKey( void )
  129. {
  130. if ( m_hideKey == BUTTON_CODE_INVALID )
  131. m_hideKey = (gameuifuncs) ? gameuifuncs->GetButtonCodeForBind( "nav_gui" ) : BUTTON_CODE_INVALID;
  132. }
  133. //--------------------------------------------------------------------------------------------------------
  134. void CNavUICheckButton::OnKeyCodePressed( KeyCode code )
  135. {
  136. LookupKey();
  137. if ( code == m_hideKey )
  138. {
  139. m_hidePressedTimer.Start();
  140. return;
  141. }
  142. BaseClass::OnKeyCodePressed( code );
  143. }
  144. //--------------------------------------------------------------------------------------------------------
  145. void CNavUICheckButton::OnKeyCodeReleased( KeyCode code )
  146. {
  147. LookupKey();
  148. if ( code == m_hideKey )
  149. {
  150. if ( m_hidePressedTimer.HasStarted() && m_hidePressedTimer.GetElapsedTime() < 0.5f )
  151. {
  152. s_navUIPanel->ToggleVisibility();
  153. m_hidePressedTimer.Invalidate();
  154. }
  155. return;
  156. }
  157. BaseClass::OnKeyCodeReleased( code );
  158. }
  159. //--------------------------------------------------------------------------------------------------------
  160. CNavUIBasePanel::CNavUIBasePanel() : vgui::Frame( NULL, "NavUI" )
  161. {
  162. m_hideKey = BUTTON_CODE_INVALID;
  163. SetScheme( "SourceScheme" );
  164. LoadControlSettings( "Resource/UI/NavUI.res" );
  165. SetAlpha( 0 );
  166. SetMouseInputEnabled( false );
  167. SetSizeable( false );
  168. SetMoveable( false );
  169. SetCloseButtonVisible( false );
  170. SetTitleBarVisible( false );
  171. SetLeftClickAction( "", "" );
  172. m_hidden = false;
  173. m_toolPanel = NULL;
  174. m_selectionPanel = NULL;
  175. SetTitle( "", true);
  176. m_dragSelecting = m_dragUnselecting = false;
  177. MenuButton *menuButton = dynamic_cast< MenuButton * >(FindChildByName( "FileMenuButton" ));
  178. if ( menuButton )
  179. {
  180. NavMenu * menu = new NavMenu( menuButton, "NavFileMenu" );
  181. menu->AddMenuItem( "Quit", "Quit", new KeyValues( "Command", "command", "StopEditing" ), this );
  182. menuButton->SetMenu( menu );
  183. menuButton->SetOpenDirection( Menu::DOWN );
  184. }
  185. menuButton = dynamic_cast< MenuButton * >(FindChildByName( "SelectionMenuButton" ));
  186. if ( menuButton )
  187. {
  188. NavMenu * menu = new NavMenu( menuButton, "NavSelectionMenu" );
  189. menu->AddMenuItem( "Flood Select", "Flood Select", new KeyValues( "Command", "command", "FloodSelect" ), this );
  190. menu->AddMenuItem( "Flood Select (fog)", "Flood Select (Fog)", new KeyValues( "Command", "command", "FloodSelect fog" ), this );
  191. menuButton->SetMenu( menu );
  192. menuButton->SetOpenDirection( Menu::DOWN );
  193. }
  194. }
  195. //--------------------------------------------------------------------------------------------------------
  196. CNavUIBasePanel::~CNavUIBasePanel()
  197. {
  198. s_navUIPanel = NULL;
  199. }
  200. //--------------------------------------------------------------------------------------------------------
  201. void CNavUIBasePanel::SetLeftClickAction( const char *action, const char *text )
  202. {
  203. if ( !action || !*action )
  204. {
  205. action = "Selection::Select";
  206. }
  207. if ( !text || !*text )
  208. {
  209. text = "Select";
  210. }
  211. V_strncpy( m_leftClickAction, action, sizeof( m_leftClickAction ) );
  212. m_performingLeftClickAction = false;
  213. vgui::Label *label = dynamic_cast< vgui::Label * >(FindChildByName( "LeftClick" ) );
  214. if ( label )
  215. {
  216. label->SetText( UTIL_VarArgs( "Left Click: %s", text ) );
  217. }
  218. }
  219. //--------------------------------------------------------------------------------------------------------
  220. void CNavUIBasePanel::ApplySchemeSettings( IScheme *pScheme )
  221. {
  222. BaseClass::ApplySchemeSettings( pScheme );
  223. SetBgColor( Color( 0, 0, 0, 0 ) );
  224. Panel *panel = FindChildByName( "SidebarParent" );
  225. if ( panel )
  226. {
  227. panel->SetBgColor( Color( 128, 128, 128, 255 ) );
  228. panel->SetPaintBackgroundType( 2 );
  229. }
  230. panel = FindChildByName( "MenuParent" );
  231. if ( panel )
  232. {
  233. panel->SetBgColor( Color( 128, 128, 128, 255 ) );
  234. panel->SetPaintBackgroundType( 0 );
  235. }
  236. panel = FindChildByName( "ToolParent" );
  237. if ( panel )
  238. {
  239. panel->SetBgColor( Color( 0, 0, 0, 128 ) );
  240. panel->SetPaintBackgroundType( 0 );
  241. }
  242. panel = FindChildByName( "SelectionParent" );
  243. if ( panel )
  244. {
  245. panel->SetBgColor( Color( 0, 0, 0, 128 ) );
  246. panel->SetPaintBackgroundType( 0 );
  247. }
  248. panel = FindChildByName( "MouseFeedbackParent" );
  249. if ( panel )
  250. {
  251. panel->SetBgColor( Color( 0, 0, 0, 128 ) );
  252. panel->SetPaintBackgroundType( 0 );
  253. }
  254. }
  255. //--------------------------------------------------------------------------------------------------------
  256. void CNavUIBasePanel::PerformLayout( void )
  257. {
  258. int wide, tall;
  259. vgui::surface()->GetScreenSize( wide, tall );
  260. SetBounds( 0, 0, wide, tall );
  261. Panel *panel = FindChildByName( "MenuParent" );
  262. if ( panel )
  263. {
  264. int oldWide, oldTall;
  265. panel->GetSize( oldWide, oldTall );
  266. panel->SetSize( wide, oldTall );
  267. }
  268. BaseClass::PerformLayout();
  269. }
  270. //--------------------------------------------------------------------------------------------------------
  271. void CNavUIBasePanel::PaintBackground( void )
  272. {
  273. BaseClass::PaintBackground();
  274. }
  275. //--------------------------------------------------------------------------------------------------------
  276. const char *CNavUIBasePanel::ActiveToolName( void ) const
  277. {
  278. if ( m_toolPanel )
  279. return m_toolPanel->GetName();
  280. return "";
  281. }
  282. //--------------------------------------------------------------------------------------------------------
  283. void CNavUIBasePanel::ActivateTool( const char *toolName )
  284. {
  285. if ( m_toolPanel && FStrEq( m_toolPanel->GetName(), toolName ) )
  286. {
  287. m_toolPanel->Shutdown();
  288. m_toolPanel->MarkForDeletion();
  289. m_toolPanel = NULL;
  290. }
  291. else
  292. {
  293. if ( m_toolPanel )
  294. {
  295. m_toolPanel->Shutdown();
  296. m_toolPanel->MarkForDeletion();
  297. m_toolPanel = NULL;
  298. }
  299. Panel *toolParent = FindChildByName( "ToolParent" );
  300. if ( !toolParent )
  301. toolParent = this;
  302. m_toolPanel = CreateTool( toolName, toolParent );
  303. if ( m_toolPanel )
  304. {
  305. m_toolPanel->Init();
  306. m_toolPanel->SetVisible( true );
  307. }
  308. }
  309. }
  310. //--------------------------------------------------------------------------------------------------------
  311. CNavUIToolPanel *CNavUIBasePanel::CreateTool( const char *toolName, vgui::Panel *toolParent )
  312. {
  313. if ( FStrEq( toolName, "Selection" ) )
  314. {
  315. return new SelectionToolPanel( toolParent, toolName );
  316. }
  317. if ( FStrEq( toolName, "Mesh" ) )
  318. {
  319. return new MeshToolPanel( toolParent, toolName );
  320. }
  321. if ( FStrEq( toolName, "Attribute" ) )
  322. {
  323. return new AttributeToolPanel( toolParent, toolName );
  324. }
  325. return NULL;
  326. }
  327. //--------------------------------------------------------------------------------------------------------
  328. void CNavUIBasePanel::OnCommand( const char *command )
  329. {
  330. CSplitString argv( command, " " );
  331. if ( FStrEq( "Close", command ) )
  332. {
  333. ToggleVisibility();
  334. }
  335. else if ( FStrEq( "MeshTool", command ) )
  336. {
  337. ActivateTool( "Mesh" );
  338. return;
  339. }
  340. else if ( FStrEq( "AttributesTool", command ) )
  341. {
  342. ActivateTool( "Attribute" );
  343. return;
  344. }
  345. else if ( FStrEq( "StopEditing", command ) )
  346. {
  347. MarkForDeletion();
  348. engine->ServerCommand( "nav_edit 0\n" );
  349. }
  350. else
  351. {
  352. BaseClass::OnCommand( command );
  353. }
  354. // argv can't delete individual elements
  355. }
  356. //--------------------------------------------------------------------------------------------------------
  357. // GameUI panels are always visible by default, so here we hide ourselves if the GameUI is up.
  358. void CNavUIBasePanel::OnTick( void )
  359. {
  360. CBasePlayer *player = UTIL_GetListenServerHost();
  361. if ( !player || !player->IsConnected() )
  362. {
  363. m_hidden = true;
  364. SetVisible( false );
  365. vgui::ivgui()->RemoveTickSignal( GetVPanel() );
  366. return;
  367. }
  368. if ( enginevgui->IsGameUIVisible() )
  369. {
  370. if ( GetAlpha() != 0 )
  371. {
  372. SetAlpha( 0 );
  373. SetMouseInputEnabled( false );
  374. }
  375. }
  376. else
  377. {
  378. if ( m_hidden )
  379. {
  380. if ( GetAlpha() > 0 )
  381. {
  382. SetAlpha( 0 );
  383. SetMouseInputEnabled( false );
  384. }
  385. SetVisible( false );
  386. vgui::ivgui()->RemoveTickSignal( GetVPanel() );
  387. return;
  388. }
  389. else
  390. {
  391. if ( GetAlpha() < 255 )
  392. {
  393. SetAlpha( 255 );
  394. SetMouseInputEnabled( true );
  395. if ( !m_selectionPanel )
  396. {
  397. Panel *selectionParent = FindChildByName( "SelectionParent" );
  398. if ( !selectionParent )
  399. selectionParent = this;
  400. m_selectionPanel = CreateTool( "Selection", selectionParent );
  401. if ( m_selectionPanel )
  402. {
  403. m_selectionPanel->Init();
  404. m_selectionPanel->SetVisible( true );
  405. }
  406. }
  407. }
  408. CFmtStr str;
  409. if ( m_toolPanel )
  410. {
  411. str.sprintf( "%s - %s", STRING( gpGlobals->mapname ), m_toolPanel->GetName() );
  412. }
  413. else
  414. {
  415. str.sprintf( "%s", STRING( gpGlobals->mapname ) );
  416. }
  417. SetTitle( str.Access(), true );
  418. }
  419. }
  420. }
  421. //--------------------------------------------------------------------------------------------------------
  422. void CNavUIBasePanel::ToggleVisibility( void )
  423. {
  424. m_hidden = !m_hidden;
  425. if ( m_hidden && NavGUIRebuild.GetBool() )
  426. {
  427. MarkForDeletion();
  428. s_navUIPanel = NULL;
  429. }
  430. }
  431. //--------------------------------------------------------------------------------------------------------
  432. Panel *CNavUIBasePanel::CreateControlByName( const char *controlName )
  433. {
  434. if ( FStrEq( controlName, "Button" ) )
  435. {
  436. return new CNavUIButton( this, "CNavUIButton" );
  437. }
  438. if ( FStrEq( controlName, "TextEntry" ) )
  439. {
  440. return new CNavUITextEntry( this, "CNavUITextEntry" );
  441. }
  442. if ( FStrEq( controlName, "ComboBox" ) )
  443. {
  444. return new CNavUIComboBox( this, "CNavUIComboBox", 5, false );
  445. }
  446. if ( FStrEq( controlName, "CheckButton" ) )
  447. {
  448. return new CNavUICheckButton( this, "CNavUICheckButton", "" );
  449. }
  450. return BaseClass::CreateControlByName( controlName );
  451. }
  452. //--------------------------------------------------------------------------------------------------------
  453. Panel *CNavUIToolPanel::CreateControlByName( const char *controlName )
  454. {
  455. if ( s_navUIPanel )
  456. {
  457. return s_navUIPanel->CreateControlByName( controlName );
  458. }
  459. return BaseClass::CreateControlByName( controlName );
  460. }
  461. //--------------------------------------------------------------------------------------------------------
  462. bool CNavUIToolPanel::IsCheckButtonChecked( const char *name )
  463. {
  464. vgui::CheckButton *checkButton = dynamic_cast< vgui::CheckButton * >( FindChildByName( name, true ) );
  465. if ( !checkButton )
  466. return false;
  467. return checkButton->IsSelected();
  468. }
  469. //--------------------------------------------------------------------------------------------------------
  470. void CNavUIBasePanel::LookupKey( void )
  471. {
  472. if ( m_hideKey == BUTTON_CODE_INVALID )
  473. m_hideKey = (gameuifuncs) ? gameuifuncs->GetButtonCodeForBind( "nav_gui" ) : BUTTON_CODE_INVALID;
  474. }
  475. //--------------------------------------------------------------------------------------------------------
  476. void CNavUIBasePanel::OnKeyCodePressed( KeyCode code )
  477. {
  478. LookupKey();
  479. if ( code == m_hideKey )
  480. {
  481. m_hidePressedTimer.Start();
  482. return;
  483. }
  484. BaseClass::OnKeyCodePressed( code );
  485. }
  486. //--------------------------------------------------------------------------------------------------------
  487. void CNavUIBasePanel::OnKeyCodeReleased( KeyCode code )
  488. {
  489. LookupKey();
  490. if ( code == m_hideKey )
  491. {
  492. if ( m_hidePressedTimer.HasStarted() && m_hidePressedTimer.GetElapsedTime() < 0.5f )
  493. {
  494. s_navUIPanel->ToggleVisibility();
  495. m_hidePressedTimer.Invalidate();
  496. }
  497. return;
  498. }
  499. BaseClass::OnKeyCodeReleased( code );
  500. }
  501. //--------------------------------------------------------------------------------------------------------
  502. void CNavUIBasePanel::OnCursorEntered( void )
  503. {
  504. BaseClass::OnCursorEntered();
  505. if ( m_performingLeftClickAction )
  506. {
  507. if ( m_toolPanel )
  508. {
  509. m_toolPanel->FinishLeftClickAction( m_leftClickAction );
  510. }
  511. if ( m_selectionPanel )
  512. {
  513. m_selectionPanel->FinishLeftClickAction( m_leftClickAction );
  514. }
  515. m_performingLeftClickAction = false;
  516. }
  517. }
  518. //--------------------------------------------------------------------------------------------------------
  519. void CNavUIBasePanel::OnCursorMoved( int x, int y )
  520. {
  521. if ( m_toolPanel )
  522. {
  523. m_toolPanel->OnCursorMoved( x, y );
  524. }
  525. if ( m_selectionPanel )
  526. {
  527. m_selectionPanel->OnCursorMoved( x, y );
  528. }
  529. BaseClass::OnCursorMoved( x, y );
  530. }
  531. //--------------------------------------------------------------------------------------------------------
  532. void CNavUIBasePanel::OnCursorExited( void )
  533. {
  534. BaseClass::OnCursorExited();
  535. if ( m_performingLeftClickAction )
  536. {
  537. if ( m_toolPanel )
  538. {
  539. m_toolPanel->FinishLeftClickAction( m_leftClickAction );
  540. }
  541. if ( m_selectionPanel )
  542. {
  543. m_selectionPanel->FinishLeftClickAction( m_leftClickAction );
  544. }
  545. m_performingLeftClickAction = false;
  546. }
  547. /*
  548. if ( m_dragSelecting || m_dragUnselecting )
  549. {
  550. PlaySound( "EDIT_END_AREA.Creating" );
  551. }
  552. m_dragSelecting = false;
  553. m_dragUnselecting = false;
  554. */
  555. }
  556. //--------------------------------------------------------------------------------------------------------
  557. void CNavUIBasePanel::OnMousePressed( MouseCode code )
  558. {
  559. /*
  560. CNavArea *area = TheNavMesh->GetSelectedArea();
  561. */
  562. switch ( code )
  563. {
  564. case MOUSE_LEFT:
  565. m_performingLeftClickAction = true;
  566. if ( m_toolPanel )
  567. {
  568. m_toolPanel->StartLeftClickAction( m_leftClickAction );
  569. }
  570. if ( m_selectionPanel )
  571. {
  572. m_selectionPanel->StartLeftClickAction( m_leftClickAction );
  573. }
  574. break;
  575. }
  576. BaseClass::OnMousePressed( code );
  577. }
  578. //--------------------------------------------------------------------------------------------------------
  579. void CNavUIBasePanel::OnMouseReleased( MouseCode code )
  580. {
  581. switch ( code )
  582. {
  583. case MOUSE_LEFT:
  584. if ( m_performingLeftClickAction )
  585. {
  586. if ( m_toolPanel )
  587. {
  588. m_toolPanel->FinishLeftClickAction( m_leftClickAction );
  589. }
  590. if ( m_selectionPanel )
  591. {
  592. m_selectionPanel->FinishLeftClickAction( m_leftClickAction );
  593. }
  594. m_performingLeftClickAction = false;
  595. }
  596. break;
  597. case MOUSE_RIGHT:
  598. if ( m_toolPanel )
  599. {
  600. m_toolPanel->StartRightClickAction( "Selection::ClearSelection" );
  601. }
  602. if ( m_selectionPanel )
  603. {
  604. m_selectionPanel->StartRightClickAction( "Selection::ClearSelection" );
  605. }
  606. break;
  607. }
  608. BaseClass::OnMousePressed( code );
  609. }
  610. //--------------------------------------------------------------------------------------------------------
  611. void CNavUIBasePanel::PlaySound( const char *sound )
  612. {
  613. CBasePlayer *player = UTIL_GetListenServerHost();
  614. if ( player )
  615. {
  616. player->EmitSound( sound );
  617. }
  618. }
  619. //--------------------------------------------------------------------------------------------------------
  620. // Taken from cl_dll/view.cpp
  621. float ScaleFOVByWidthRatio( float fovDegrees, float ratio )
  622. {
  623. float halfAngleRadians = fovDegrees * ( 0.5f * M_PI / 180.0f );
  624. float t = tan( halfAngleRadians );
  625. t *= ratio;
  626. float retDegrees = ( 180.0f / M_PI ) * atan( t );
  627. return retDegrees * 2.0f;
  628. }
  629. //--------------------------------------------------------------------------------------------------------
  630. // Purpose:
  631. // Given a field of view and mouse/screen positions as well as the current
  632. // render origin and angles, returns a unit vector through the mouse position
  633. // that can be used to trace into the world under the mouse click pixel.
  634. // Input :
  635. // mousex -
  636. // mousey -
  637. // fov -
  638. // vecRenderOrigin -
  639. // vecRenderAngles -
  640. // Output :
  641. // vecPickingRay
  642. // Adapted from cl_dll/c_vguiscreen.cpp
  643. //--------------------------------------------------------------------------------------------------------
  644. void ScreenToWorld( int mousex, int mousey, float fov,
  645. const Vector& vecRenderOrigin,
  646. const QAngle& vecRenderAngles,
  647. Vector& vecPickingRay )
  648. {
  649. float dx, dy;
  650. float c_x, c_y;
  651. float dist;
  652. Vector vpn, vup, vright;
  653. int wide, tall;
  654. vgui::surface()->GetScreenSize( wide, tall );
  655. c_x = wide / 2;
  656. c_y = tall / 2;
  657. float scaled_fov = ScaleFOVByWidthRatio( fov, (float)wide / (float)tall * 0.75f );
  658. dx = (float)mousex - c_x;
  659. // Invert Y
  660. dy = c_y - (float)mousey;
  661. // Convert view plane distance
  662. dist = c_x / tan( M_PI * scaled_fov / 360.0 );
  663. // Decompose view angles
  664. AngleVectors( vecRenderAngles, &vpn, &vright, &vup );
  665. // Offset forward by view plane distance, and then by pixel offsets
  666. vecPickingRay = vpn * dist + vright * ( dx ) + vup * ( dy );
  667. // Convert to unit vector
  668. VectorNormalize( vecPickingRay );
  669. }
  670. //--------------------------------------------------------------------------------------------------------
  671. void GetNavUIEditVectors( Vector *pos, Vector *forward )
  672. {
  673. CBasePlayer *player = UTIL_GetListenServerHost();
  674. if ( !player )
  675. {
  676. return;
  677. }
  678. if ( !s_navUIPanel )
  679. {
  680. return;
  681. }
  682. if ( s_navUIPanel->GetAlpha() < 255 )
  683. {
  684. return;
  685. }
  686. int x, y;
  687. vgui::surface()->SurfaceGetCursorPos( x, y );
  688. float fov = player->GetFOV();
  689. QAngle eyeAngles = player->EyeAngles();
  690. Vector eyePosition = player->EyePosition();
  691. Vector pick;
  692. ScreenToWorld( x, y, fov, eyePosition, eyeAngles, pick );
  693. *forward = pick;
  694. }
  695. //--------------------------------------------------------------------------------------------------------
  696. void NavUICommand( void )
  697. {
  698. if ( engine->IsDedicatedServer() )
  699. return;
  700. if ( UTIL_GetCommandClient() != UTIL_GetListenServerHost() )
  701. return;
  702. engine->ServerCommand( "nav_edit 1\n" );
  703. bool created = false;
  704. if ( !s_navUIPanel )
  705. {
  706. created = true;
  707. s_navUIPanel = CreateNavUI();
  708. }
  709. ShowGameDLLPanel( s_navUIPanel );
  710. vgui::ivgui()->AddTickSignal( s_navUIPanel->GetVPanel() );
  711. if ( !created )
  712. {
  713. s_navUIPanel->ToggleVisibility();
  714. }
  715. }
  716. ConCommand nav_gui( "nav_gui", NavUICommand, "Opens the nav editing GUI", FCVAR_CHEAT );
  717. #endif // SERVER_USES_VGUI
  718. //--------------------------------------------------------------------------------------------------------