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.

1443 lines
42 KiB

  1. //===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "cbase.h"
  7. #include "view.h"
  8. #include "iviewrender.h"
  9. #include "iviewrender_beams.h"
  10. #include "view_shared.h"
  11. #include "ivieweffects.h"
  12. #include "iinput.h"
  13. #include "iclientmode.h"
  14. #include "prediction.h"
  15. #include "viewrender.h"
  16. #include "c_te_legacytempents.h"
  17. #include "cl_mat_stub.h"
  18. #include "tier0/vprof.h"
  19. #include "iclientvehicle.h"
  20. #include "engine/IEngineTrace.h"
  21. #include "mathlib/vmatrix.h"
  22. #include "rendertexture.h"
  23. #include "c_world.h"
  24. #include <keyvalues.h>
  25. #include "igameevents.h"
  26. #include "smoke_fog_overlay.h"
  27. #include "bitmap/tgawriter.h"
  28. #include "hltvcamera.h"
  29. #if defined( REPLAY_ENABLED )
  30. #include "replaycamera.h"
  31. #endif
  32. #include "input.h"
  33. #include "filesystem.h"
  34. #include "materialsystem/itexture.h"
  35. #include "toolframework_client.h"
  36. #include "tier0/icommandline.h"
  37. #include "ienginevgui.h"
  38. #include <vgui_controls/Controls.h>
  39. #include <vgui/ISurface.h>
  40. #include "ScreenSpaceEffects.h"
  41. #include "vgui_int.h"
  42. #include "engine/SndInfo.h"
  43. #if defined( CSTRIKE15 )
  44. #include "c_cs_player.h"
  45. #endif
  46. #ifdef GAMEUI_UISYSTEM2_ENABLED
  47. #include "gameui.h"
  48. #endif
  49. #ifdef GAMEUI_EMBEDDED
  50. #if defined( PORTAL2 )
  51. #include "gameui/basemodpanel.h"
  52. #elif defined( SWARM_DLL )
  53. #include "swarm/gameui/swarm/basemodpanel.h"
  54. #elif defined( CSTRIKE15 )
  55. #include "gameui/basemodpanel.h"
  56. #else
  57. #error "GAMEUI_EMBEDDED"
  58. #endif
  59. #endif
  60. #if defined( HL2_CLIENT_DLL ) || defined( CSTRIKE_DLL ) || defined( INFESTED_DLL )
  61. #define USE_MONITORS
  62. #endif
  63. #ifdef PORTAL
  64. #include "C_Prop_Portal.h" //portal surface rendering functions
  65. #endif
  66. // memdbgon must be the last include file in a .cpp file!!!
  67. #include "tier0/memdbgon.h"
  68. void ToolFramework_AdjustEngineViewport( int& x, int& y, int& width, int& height );
  69. bool ToolFramework_SetupEngineView( Vector &origin, QAngle &angles, float &fov );
  70. bool ToolFramework_SetupEngineMicrophone( Vector &origin, QAngle &angles );
  71. extern ConVar default_fov;
  72. extern bool g_bRenderingScreenshot;
  73. #define SAVEGAME_SCREENSHOT_WIDTH 256
  74. #define SAVEGAME_SCREENSHOT_HEIGHT 256
  75. extern ConVar sensitivity;
  76. ConVar zoom_sensitivity_ratio_joystick( "zoom_sensitivity_ratio_joystick", "1.0", FCVAR_ARCHIVE | FCVAR_SS, "Additional controller sensitivity scale factor applied when FOV is zoomed in." );
  77. ConVar zoom_sensitivity_ratio_mouse( "zoom_sensitivity_ratio_mouse", "1.0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE | FCVAR_SS, "Additional mouse sensitivity scale factor applied when FOV is zoomed in." );
  78. // Each MOD implements GetViewRenderInstance() and provides either a default object or a subclassed object!!!
  79. IViewRender *view = NULL; // set in cldll_client_init.cpp if no mod creates their own
  80. #if _DEBUG
  81. bool g_bRenderingCameraView = false;
  82. #endif
  83. static Vector g_vecRenderOrigin[ MAX_SPLITSCREEN_PLAYERS ];
  84. static QAngle g_vecRenderAngles[ MAX_SPLITSCREEN_PLAYERS ];
  85. static Vector g_vecPrevRenderOrigin[ MAX_SPLITSCREEN_PLAYERS ]; // Last frame's render origin
  86. static QAngle g_vecPrevRenderAngles[ MAX_SPLITSCREEN_PLAYERS ]; // Last frame's render angles
  87. static Vector g_vecVForward[ MAX_SPLITSCREEN_PLAYERS ], g_vecVRight[ MAX_SPLITSCREEN_PLAYERS ], g_vecVUp[ MAX_SPLITSCREEN_PLAYERS ];
  88. static VMatrix g_matCamInverse[ MAX_SPLITSCREEN_PLAYERS ];
  89. extern ConVar cl_forwardspeed;
  90. static ConVar v_centermove( "v_centermove", "0.15");
  91. static ConVar v_centerspeed( "v_centerspeed","500" );
  92. // 54 degrees approximates a 35mm camera - we determined that this makes the viewmodels
  93. // and motions look the most natural.
  94. ConVar v_viewmodel_fov( "viewmodel_fov", "54", FCVAR_ARCHIVE );
  95. ConVar mat_viewportscale( "mat_viewportscale", "1.0", FCVAR_CHEAT, "Scale down the main viewport (to reduce GPU impact on CPU profiling)",
  96. true, (1.0f / 640.0f), true, 1.0f );
  97. ConVar mat_viewportupscale( "mat_viewportupscale", "1", FCVAR_CHEAT, "Scale the viewport back up" );
  98. ConVar cl_leveloverview( "cl_leveloverview", "0", FCVAR_CHEAT );
  99. ConVar r_mapextents( "r_mapextents", "16384", FCVAR_CHEAT,
  100. "Set the max dimension for the map. This determines the far clipping plane" );
  101. static ConVar cl_camera_follow_bone_index( "cl_camera_follow_bone_index" , "-2", FCVAR_CHEAT, "Index of the bone to follow. -2 == disabled. -1 == root bone. 0+ is bone index." );
  102. Vector g_cameraFollowPos;
  103. // UNDONE: Delete this or move to the material system?
  104. ConVar gl_clear( "gl_clear", "0",
  105. #if defined( ALLOW_TEXT_MODE )
  106. FCVAR_RELEASE
  107. #else
  108. 0
  109. #endif
  110. );
  111. ConVar gl_clear_randomcolor( "gl_clear_randomcolor", "0", FCVAR_CHEAT, "Clear the back buffer to random colors every frame. Helps spot open seams in geometry." );
  112. static ConVar r_farz( "r_farz", "-1", FCVAR_CHEAT, "Override the far clipping plane. -1 means to use the value in env_fog_controller." );
  113. #ifdef _DEBUG
  114. static ConVar r_nearz( "r_nearz", "-1", FCVAR_CHEAT, "Override the near clipping plane. -1 means to not override." );
  115. #endif
  116. static ConVar cl_demoviewoverride( "cl_demoviewoverride", "0", 0, "Override view during demo playback" );
  117. static Vector s_DemoView;
  118. static QAngle s_DemoAngle;
  119. static void CalcDemoViewOverride( Vector &origin, QAngle &angles )
  120. {
  121. engine->SetViewAngles( s_DemoAngle );
  122. input->ExtraMouseSample( gpGlobals->absoluteframetime, true );
  123. engine->GetViewAngles( s_DemoAngle );
  124. Vector forward, right, up;
  125. AngleVectors( s_DemoAngle, &forward, &right, &up );
  126. float speed = gpGlobals->absoluteframetime * cl_demoviewoverride.GetFloat() * 320;
  127. s_DemoView += speed * input->KeyState (&in_forward) * forward ;
  128. s_DemoView -= speed * input->KeyState (&in_back) * forward ;
  129. s_DemoView += speed * input->KeyState (&in_moveright) * right ;
  130. s_DemoView -= speed * input->KeyState (&in_moveleft) * right ;
  131. origin = s_DemoView;
  132. angles = s_DemoAngle;
  133. }
  134. CViewSetup &CViewRender::GetView(int nSlot /*= -1*/)
  135. {
  136. Assert( m_bAllowViewAccess );
  137. if ( nSlot == -1 )
  138. {
  139. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  140. return m_UserView[ GET_ACTIVE_SPLITSCREEN_SLOT() ];
  141. }
  142. return m_UserView[ nSlot ];
  143. }
  144. const CViewSetup &CViewRender::GetView(int nSlot /*= -1*/) const
  145. {
  146. Assert( m_bAllowViewAccess );
  147. if ( nSlot == -1 )
  148. {
  149. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  150. return m_UserView[ GET_ACTIVE_SPLITSCREEN_SLOT() ];
  151. }
  152. return m_UserView[ nSlot ];
  153. }
  154. //-----------------------------------------------------------------------------
  155. // Accessors to return the main view (where the player's looking)
  156. //-----------------------------------------------------------------------------
  157. const Vector &MainViewOrigin( int nSlot )
  158. {
  159. return g_vecRenderOrigin[ nSlot ];
  160. }
  161. const QAngle &MainViewAngles( int nSlot )
  162. {
  163. return g_vecRenderAngles[ nSlot ];
  164. }
  165. const Vector &MainViewForward( int nSlot )
  166. {
  167. return g_vecVForward[ nSlot ];
  168. }
  169. const Vector &MainViewRight( int nSlot )
  170. {
  171. return g_vecVRight[ nSlot ];
  172. }
  173. const Vector &MainViewUp( int nSlot )
  174. {
  175. return g_vecVUp[ nSlot ];
  176. }
  177. const VMatrix &MainWorldToViewMatrix( int nSlot )
  178. {
  179. return g_matCamInverse[ nSlot ];
  180. }
  181. const Vector &PrevMainViewOrigin( int nSlot )
  182. {
  183. return g_vecPrevRenderOrigin[ nSlot ];
  184. }
  185. const QAngle &PrevMainViewAngles( int nSlot )
  186. {
  187. return g_vecPrevRenderAngles[ nSlot ];
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Compute the world->camera transform
  191. //-----------------------------------------------------------------------------
  192. void ComputeCameraVariables( const Vector &vecOrigin, const QAngle &vecAngles,
  193. Vector *pVecForward, Vector *pVecRight, Vector *pVecUp, VMatrix *pMatCamInverse )
  194. {
  195. // Compute view bases
  196. AngleVectors( vecAngles, pVecForward, pVecRight, pVecUp );
  197. for (int i = 0; i < 3; ++i)
  198. {
  199. (*pMatCamInverse)[0][i] = (*pVecRight)[i];
  200. (*pMatCamInverse)[1][i] = (*pVecUp)[i];
  201. (*pMatCamInverse)[2][i] = -(*pVecForward)[i];
  202. (*pMatCamInverse)[3][i] = 0.0F;
  203. }
  204. (*pMatCamInverse)[0][3] = -DotProduct( *pVecRight, vecOrigin );
  205. (*pMatCamInverse)[1][3] = -DotProduct( *pVecUp, vecOrigin );
  206. (*pMatCamInverse)[2][3] = DotProduct( *pVecForward, vecOrigin );
  207. (*pMatCamInverse)[3][3] = 1.0F;
  208. }
  209. bool R_CullSphere(
  210. VPlane const *pPlanes,
  211. int nPlanes,
  212. Vector const *pCenter,
  213. float radius)
  214. {
  215. for(int i=0; i < nPlanes; i++)
  216. if(pPlanes[i].DistTo(*pCenter) < -radius)
  217. return true;
  218. return false;
  219. }
  220. //-----------------------------------------------------------------------------
  221. // Purpose:
  222. //-----------------------------------------------------------------------------
  223. static void StartPitchDrift( void )
  224. {
  225. view->StartPitchDrift();
  226. }
  227. static ConCommand centerview( "centerview", StartPitchDrift );
  228. //-----------------------------------------------------------------------------
  229. // Purpose: Initializes all view systems
  230. //-----------------------------------------------------------------------------
  231. void CViewRender::Init( void )
  232. {
  233. memset( &m_PitchDrift, 0, sizeof( m_PitchDrift ) );
  234. m_bDrawOverlay = false;
  235. m_pDrawEntities = cvar->FindVar( "r_drawentities" );
  236. m_pDrawBrushModels = cvar->FindVar( "r_drawbrushmodels" );
  237. beams->InitBeams();
  238. tempents->Init();
  239. m_TranslucentSingleColor.Init( "debug/debugtranslucentsinglecolor", TEXTURE_GROUP_OTHER );
  240. m_ModulateSingleColor.Init( "engine/modulatesinglecolor", TEXTURE_GROUP_OTHER );
  241. m_WhiteMaterial.Init( "vgui/white", TEXTURE_GROUP_OTHER );
  242. extern CMaterialReference g_material_WriteZ;
  243. g_material_WriteZ.Init( "engine/writez", TEXTURE_GROUP_OTHER );
  244. for ( int i = 0; i < MAX_SPLITSCREEN_PLAYERS ; ++i )
  245. {
  246. g_vecRenderOrigin[ i ].Init();
  247. g_vecRenderAngles[ i ].Init();
  248. g_vecPrevRenderOrigin[ i ].Init();
  249. g_vecPrevRenderAngles[ i ].Init();
  250. g_vecVForward[ i ].Init();
  251. g_vecVRight[ i ].Init();
  252. g_vecVUp[ i ].Init();
  253. g_matCamInverse[ i ].Identity();
  254. }
  255. }
  256. CMaterialReference &CViewRender::GetWhite()
  257. {
  258. return m_WhiteMaterial;
  259. }
  260. //-----------------------------------------------------------------------------
  261. // Purpose: Called once per level change
  262. //-----------------------------------------------------------------------------
  263. void CViewRender::LevelInit( void )
  264. {
  265. beams->ClearBeams();
  266. tempents->Clear();
  267. m_BuildWorldListsNumber = 0;
  268. m_BuildRenderableListsNumber = 0;
  269. for ( int i = 0 ; i < MAX_SPLITSCREEN_PLAYERS; ++i )
  270. {
  271. m_FreezeParams[ i ].m_bTakeFreezeFrame = false;
  272. m_FreezeParams[ i ].m_flFreezeFrameUntil = 0;
  273. }
  274. // Clear our overlay materials
  275. m_ScreenOverlayMaterial.Init( NULL );
  276. // Init all IScreenSpaceEffects
  277. g_pScreenSpaceEffects->InitScreenSpaceEffects( );
  278. InitFadeData();
  279. }
  280. //-----------------------------------------------------------------------------
  281. // Purpose: Called once per level change
  282. //-----------------------------------------------------------------------------
  283. void CViewRender::LevelShutdown( void )
  284. {
  285. g_pScreenSpaceEffects->ShutdownScreenSpaceEffects( );
  286. }
  287. //-----------------------------------------------------------------------------
  288. // Purpose: Called at shutdown
  289. //-----------------------------------------------------------------------------
  290. void CViewRender::Shutdown( void )
  291. {
  292. m_TranslucentSingleColor.Shutdown();
  293. m_ModulateSingleColor.Shutdown();
  294. m_ScreenOverlayMaterial.Shutdown();
  295. m_UnderWaterOverlayMaterial.Shutdown();
  296. m_WhiteMaterial.Shutdown();
  297. beams->ShutdownBeams();
  298. tempents->Shutdown();
  299. }
  300. //-----------------------------------------------------------------------------
  301. // Returns the worldlists build number
  302. //-----------------------------------------------------------------------------
  303. int CViewRender::BuildWorldListsNumber( void ) const
  304. {
  305. return m_BuildWorldListsNumber;
  306. }
  307. //-----------------------------------------------------------------------------
  308. // Purpose: Start moving pitch toward ideal
  309. //-----------------------------------------------------------------------------
  310. void CViewRender::StartPitchDrift (void)
  311. {
  312. if ( m_PitchDrift.laststop == gpGlobals->curtime )
  313. {
  314. // Something else is blocking the drift.
  315. return;
  316. }
  317. if ( m_PitchDrift.nodrift || !m_PitchDrift.pitchvel )
  318. {
  319. m_PitchDrift.pitchvel = v_centerspeed.GetFloat();
  320. m_PitchDrift.nodrift = false;
  321. m_PitchDrift.driftmove = 0;
  322. }
  323. }
  324. //-----------------------------------------------------------------------------
  325. // Purpose:
  326. //-----------------------------------------------------------------------------
  327. void CViewRender::StopPitchDrift (void)
  328. {
  329. m_PitchDrift.laststop = gpGlobals->curtime;
  330. m_PitchDrift.nodrift = true;
  331. m_PitchDrift.pitchvel = 0;
  332. }
  333. //-----------------------------------------------------------------------------
  334. // Purpose: Moves the client pitch angle towards cl.idealpitch sent by the server.
  335. // If the user is adjusting pitch manually, either with lookup/lookdown,
  336. // mlook and mouse, or klook and keyboard, pitch drifting is constantly stopped.
  337. //-----------------------------------------------------------------------------
  338. void CViewRender::DriftPitch (void)
  339. {
  340. float delta, move;
  341. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  342. if ( !player )
  343. return;
  344. #if defined( REPLAY_ENABLED )
  345. if ( g_bEngineIsHLTV || engine->IsReplay() || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
  346. #else
  347. if ( g_bEngineIsHLTV || ( player->GetGroundEntity() == NULL ) || engine->IsPlayingDemo() )
  348. #endif
  349. {
  350. m_PitchDrift.driftmove = 0;
  351. m_PitchDrift.pitchvel = 0;
  352. return;
  353. }
  354. // Don't count small mouse motion
  355. if ( m_PitchDrift.nodrift )
  356. {
  357. if ( fabs( input->GetLastForwardMove() ) < cl_forwardspeed.GetFloat() )
  358. {
  359. m_PitchDrift.driftmove = 0;
  360. }
  361. else
  362. {
  363. m_PitchDrift.driftmove += gpGlobals->frametime;
  364. }
  365. if ( m_PitchDrift.driftmove > v_centermove.GetFloat() )
  366. {
  367. StartPitchDrift ();
  368. }
  369. return;
  370. }
  371. // How far off are we
  372. delta = prediction->GetIdealPitch( player->GetSplitScreenPlayerSlot() ) - player->GetAbsAngles()[ PITCH ];
  373. if ( !delta )
  374. {
  375. m_PitchDrift.pitchvel = 0;
  376. return;
  377. }
  378. // Determine movement amount
  379. move = gpGlobals->frametime * m_PitchDrift.pitchvel;
  380. // Accelerate
  381. m_PitchDrift.pitchvel += gpGlobals->frametime * v_centerspeed.GetFloat();
  382. // Move predicted pitch appropriately
  383. if (delta > 0)
  384. {
  385. if ( move > delta )
  386. {
  387. m_PitchDrift.pitchvel = 0;
  388. move = delta;
  389. }
  390. player->SetLocalAngles( player->GetLocalAngles() + QAngle( move, 0, 0 ) );
  391. }
  392. else if ( delta < 0 )
  393. {
  394. if ( move > -delta )
  395. {
  396. m_PitchDrift.pitchvel = 0;
  397. move = -delta;
  398. }
  399. player->SetLocalAngles( player->GetLocalAngles() - QAngle( move, 0, 0 ) );
  400. }
  401. }
  402. // This is called by cdll_client_int to setup view model origins. This has to be done before
  403. // simulation so entities can access attachment points on view models during simulation.
  404. void CViewRender::OnRenderStart()
  405. {
  406. VPROF_("CViewRender::OnRenderStart", 2, VPROF_BUDGETGROUP_OTHER_UNACCOUNTED, false, 0);
  407. IterateRemoteSplitScreenViewSlots_Push( true );
  408. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  409. {
  410. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  411. // This will fill in one of the m_UserView[ hh ] slots
  412. SetUpView();
  413. // Adjust mouse sensitivity based upon the current FOV
  414. #if defined( CSTRIKE15 )
  415. C_CSPlayer *player = C_CSPlayer::GetLocalCSPlayer();
  416. #else
  417. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  418. #endif
  419. if ( player )
  420. {
  421. default_fov.SetValue( player->m_iDefaultFOV );
  422. //Update our FOV, including any zooms going on
  423. int iDefaultFOV = default_fov.GetInt();
  424. int localFOV = player->GetFOV();
  425. int min_fov = player->GetMinFOV();
  426. bool bZoomed = ( player->GetFOV() != player->GetDefaultFOV() );
  427. // 'scoped' mode is handled by the ironsight system
  428. /*
  429. #if defined( CSTRIKE15 )
  430. bool bScoped = player->m_bIsScoped;
  431. #else
  432. bool bScoped = bZoomed;
  433. #endif
  434. */
  435. // Don't let it go too low
  436. localFOV = MAX( min_fov, localFOV );
  437. GetHud().m_flFOVSensitivityAdjust = 1.0f;
  438. if ( GetHud().m_flMouseSensitivityFactor )
  439. {
  440. GetHud().m_flMouseSensitivity = sensitivity.GetFloat() * GetHud().m_flMouseSensitivityFactor;
  441. }
  442. else
  443. {
  444. // No override, don't use huge sensitivity
  445. if ( bZoomed == false /*&& bScoped == false*/ )
  446. {
  447. // reset to saved sensitivity
  448. GetHud().m_flMouseSensitivity = 0;
  449. }
  450. else
  451. {
  452. // Set a new sensitivity that is proportional to the change from the FOV default and scaled
  453. // by a separate compensating factor
  454. if ( iDefaultFOV == 0 )
  455. {
  456. Assert(0); // would divide by zero, something is broken with iDefatulFOV
  457. iDefaultFOV = 1;
  458. }
  459. float zoomSensitivity = zoom_sensitivity_ratio_mouse.GetFloat();
  460. if( input->ControllerModeActive() )
  461. {
  462. zoomSensitivity = zoom_sensitivity_ratio_joystick.GetFloat();
  463. }
  464. GetHud().m_flFOVSensitivityAdjust =
  465. ((float)localFOV / (float)iDefaultFOV) * // linear fov downscale
  466. zoomSensitivity; // sensitivity scale factor
  467. GetHud().m_flMouseSensitivity = GetHud().m_flFOVSensitivityAdjust * sensitivity.GetFloat(); // regular sensitivity
  468. }
  469. }
  470. }
  471. }
  472. // Setup the frustum cache for this frame.
  473. m_bAllowViewAccess = true;
  474. FOR_EACH_VALID_SPLITSCREEN_PLAYER( iSlot )
  475. {
  476. const CViewSetup &view = GetView( iSlot );
  477. FrustumCache()->Add( &view, iSlot );
  478. }
  479. FrustumCache()->SetUpdated();
  480. m_bAllowViewAccess = false;
  481. IterateRemoteSplitScreenViewSlots_Pop();
  482. }
  483. //-----------------------------------------------------------------------------
  484. // Purpose:
  485. // Output : const CViewSetup
  486. //-----------------------------------------------------------------------------
  487. const CViewSetup *CViewRender::GetViewSetup( void ) const
  488. {
  489. return &m_CurrentView;
  490. }
  491. //-----------------------------------------------------------------------------
  492. // Purpose:
  493. // Output : const CViewSetup
  494. //-----------------------------------------------------------------------------
  495. const CViewSetup *CViewRender::GetPlayerViewSetup( int nSlot /*= -1*/ ) const
  496. {
  497. // NOTE: This code path doesn't require m_bAllowViewAccess == true!!!
  498. if ( nSlot == -1 )
  499. {
  500. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  501. return &m_UserView[ GET_ACTIVE_SPLITSCREEN_SLOT() ];
  502. }
  503. return &m_UserView[ nSlot ];
  504. }
  505. //-----------------------------------------------------------------------------
  506. // Purpose:
  507. //-----------------------------------------------------------------------------
  508. void CViewRender::DisableVis( void )
  509. {
  510. m_bForceNoVis = true;
  511. }
  512. #ifdef DBGFLAG_ASSERT
  513. static Vector s_DbgSetupOrigin[ MAX_SPLITSCREEN_PLAYERS ];
  514. static QAngle s_DbgSetupAngles[ MAX_SPLITSCREEN_PLAYERS ];
  515. #endif
  516. //-----------------------------------------------------------------------------
  517. // Gets znear + zfar
  518. //-----------------------------------------------------------------------------
  519. float CViewRender::GetZNear()
  520. {
  521. #ifdef _DEBUG
  522. if ( r_nearz.GetFloat() >= 0 )
  523. return r_nearz.GetFloat();
  524. #endif
  525. // Compute aspect ratio
  526. bool bMegaWideAspectRatio = ( ( float( m_CurrentView.width ) / float( m_CurrentView.height + 1 ) ) > 2.0f );
  527. if ( !bMegaWideAspectRatio )
  528. {
  529. static ConVarRef r_aspectratio( "r_aspectratio" );
  530. if ( r_aspectratio.GetFloat() > 2.0f ) // If client is overriding aspect ratio then force znear as well
  531. bMegaWideAspectRatio = true;
  532. }
  533. return bMegaWideAspectRatio ? 1 : VIEW_NEARZ;
  534. }
  535. float CViewRender::GetZFar()
  536. {
  537. // Initialize view structure with default values
  538. float farZ;
  539. if ( r_farz.GetFloat() < 1 )
  540. {
  541. // Use the far Z from the map's parameters.
  542. farZ = r_mapextents.GetFloat() * 1.73205080757f;
  543. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  544. if( pPlayer && pPlayer->GetFogParams() )
  545. {
  546. if ( pPlayer->GetFogParams()->farz > 0 )
  547. {
  548. farZ = pPlayer->GetFogParams()->farz;
  549. }
  550. }
  551. }
  552. else
  553. {
  554. farZ = r_farz.GetFloat();
  555. }
  556. return farZ;
  557. }
  558. //-----------------------------------------------------------------------------
  559. // Sets up the view parameters
  560. //-----------------------------------------------------------------------------
  561. void CViewRender::SetUpView()
  562. {
  563. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  564. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  565. m_bAllowViewAccess = true;
  566. VPROF("CViewRender::SetUpView");
  567. // Initialize view structure with default values
  568. float farZ = GetZFar();
  569. CViewSetup &view = GetView();
  570. view.zFar = farZ;
  571. view.zFarViewmodel = farZ;
  572. // UNDONE: Make this farther out?
  573. // closest point of approach seems to be view center to top of crouched box
  574. view.zNear = GetZNear();
  575. view.zNearViewmodel = 1;
  576. view.fov = default_fov.GetFloat();
  577. view.m_bOrtho = false;
  578. // Enable spatial partition access to edicts
  579. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, false );
  580. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  581. bool bNoViewEnt = false;
  582. if( pPlayer == NULL )
  583. {
  584. pPlayer = GetSplitScreenViewPlayer( nSlot );
  585. bNoViewEnt = true;
  586. }
  587. if ( g_bEngineIsHLTV )
  588. {
  589. HLTVCamera()->CalcView( &view );
  590. }
  591. #if defined( REPLAY_ENABLED )
  592. else if ( engine->IsReplay() )
  593. {
  594. ReplayCamera()->CalcView( view.origin, view.angles, view.fov );
  595. }
  596. #endif
  597. else
  598. {
  599. // FIXME: Are there multiple views? If so, then what?
  600. // FIXME: What happens when there's no player?
  601. if (pPlayer)
  602. {
  603. pPlayer->CalcView( view.origin, view.angles, view.zNear, view.zFar, view.fov );
  604. // If we are looking through another entities eyes, then override the angles/origin for GetView()
  605. int viewentity = render->GetViewEntity();
  606. if ( !bNoViewEnt && !g_nKillCamMode && (pPlayer->entindex() != viewentity) )
  607. {
  608. C_BaseEntity *ve = cl_entitylist->GetEnt( viewentity );
  609. if ( ve )
  610. {
  611. VectorCopy( ve->GetAbsOrigin(), view.origin );
  612. VectorCopy( ve->GetAbsAngles(), view.angles );
  613. GetViewEffects()->ApplyShake( view.origin, view.angles, 1.0 );
  614. }
  615. }
  616. pPlayer->CalcViewModelView( view.origin, view.angles );
  617. // Is this the proper place for this code?
  618. if ( cl_camera_follow_bone_index.GetInt() >= -1 && input->CAM_IsThirdPerson() )
  619. {
  620. VectorCopy( g_cameraFollowPos, view.origin );
  621. }
  622. }
  623. // Even if the engine is paused need to override the view
  624. // for keeping the camera control during pause.
  625. GetClientMode()->OverrideView( &GetView() );
  626. }
  627. #if defined ( CSTRIKE15 )
  628. CBasePlayer *pCameraMan = NULL;
  629. if ( g_bEngineIsHLTV )
  630. pCameraMan = HLTVCamera()->GetCameraMan();
  631. C_CSPlayer *pCSPlayer = ( g_bEngineIsHLTV && pCameraMan ) ? static_cast< C_CSPlayer* >( pCameraMan ) : C_CSPlayer::GetLocalCSPlayer();
  632. if ( pCSPlayer && pCSPlayer->ShouldInterpolateObserverChanges() )
  633. {
  634. pCSPlayer->InterpolateObserverView( view.origin, view.angles );
  635. pCSPlayer->CalcViewModelView( view.origin, view.angles );
  636. }
  637. #endif
  638. // give the toolsystem a chance to override the view
  639. ToolFramework_SetupEngineView( view.origin, view.angles, view.fov );
  640. if ( engine->IsPlayingDemo() )
  641. {
  642. if ( cl_demoviewoverride.GetFloat() > 0.0f )
  643. {
  644. // Retreive view angles from engine ( could have been set in IN_AdjustAngles above )
  645. CalcDemoViewOverride( view.origin, view.angles );
  646. }
  647. else
  648. {
  649. s_DemoView = view.origin;
  650. s_DemoAngle = view.angles;
  651. }
  652. }
  653. // Disable spatial partition access
  654. ::partition->SuppressLists( PARTITION_ALL_CLIENT_EDICTS, true );
  655. //Find the offset our current FOV is from the default value
  656. float flFOVOffset = pPlayer ? ( pPlayer->GetDefaultFOV() - view.fov ) : 0.0f;
  657. //Adjust the viewmodel's FOV to move with any FOV offsets on the viewer's end
  658. view.fovViewmodel = GetClientMode()->GetViewModelFOV() - flFOVOffset;
  659. // Compute the world->main camera transform
  660. ComputeCameraVariables( view.origin, view.angles,
  661. &g_vecVForward[ nSlot ], &g_vecVRight[ nSlot ], &g_vecVUp[ nSlot ], &g_matCamInverse[ nSlot ] );
  662. // set up the hearing origin...
  663. AudioState_t audioState;
  664. audioState.m_Origin = view.origin;
  665. audioState.m_Angles = view.angles;
  666. audioState.m_bIsUnderwater = pPlayer && pPlayer->AudioStateIsUnderwater( view.origin );
  667. ToolFramework_SetupAudioState( audioState );
  668. view.origin = audioState.m_Origin;
  669. view.angles = audioState.m_Angles;
  670. GetClientMode()->OverrideAudioState( &audioState );
  671. engine->SetAudioState( audioState );
  672. g_vecPrevRenderOrigin[ nSlot ] = g_vecRenderOrigin[ nSlot ];
  673. g_vecPrevRenderAngles[ nSlot ] = g_vecRenderAngles[ nSlot ];
  674. g_vecRenderOrigin[ nSlot ] = view.origin;
  675. g_vecRenderAngles[ nSlot ] = view.angles;
  676. #ifdef DBGFLAG_ASSERT
  677. s_DbgSetupOrigin[ nSlot ] = view.origin;
  678. s_DbgSetupAngles[ nSlot ] = view.angles;
  679. #endif
  680. m_bAllowViewAccess = false;
  681. }
  682. void CViewRender::WriteSaveGameScreenshotOfSize( const char *pFilename, int width, int height )
  683. {
  684. g_bRenderingScreenshot = true;
  685. m_bAllowViewAccess = true;
  686. {
  687. CMatRenderContextPtr pRenderContext( materials );
  688. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  689. pRenderContext->PushMatrix();
  690. pRenderContext->MatrixMode( MATERIAL_VIEW );
  691. pRenderContext->PushMatrix();
  692. // Push back buffer on the stack with small viewport
  693. pRenderContext->PushRenderTargetAndViewport( NULL, 0, 0, width, height );
  694. // render out to the backbuffer
  695. CViewSetup viewSetup = GetView();
  696. viewSetup.x = 0;
  697. viewSetup.y = 0;
  698. viewSetup.width = width;
  699. viewSetup.height = height;
  700. viewSetup.fov = ScaleFOVByWidthRatio( GetView().fov, ( (float)width / (float)height ) / ( 4.0f / 3.0f ) );
  701. viewSetup.m_bRenderToSubrectOfLargerScreen = true;
  702. float flSavedBlurFade = GetClientMode()->GetBlurFade();
  703. GetClientMode()->SetBlurFade( 0.0f );
  704. // draw out the scene
  705. // Don't draw the HUD or the viewmodel
  706. // Note: The original code here just cleared DEPTH and COLOR, but this was somehow failing to clear the depth buffer before the Z-Prepass in non-water views on X360, corrupting the screenshot.
  707. RenderView( viewSetup, viewSetup, VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL, 0 );
  708. GetClientMode()->SetBlurFade( flSavedBlurFade );
  709. // restore our previous state
  710. pRenderContext->PopRenderTargetAndViewport();
  711. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  712. pRenderContext->PopMatrix();
  713. pRenderContext->MatrixMode( MATERIAL_VIEW );
  714. pRenderContext->PopMatrix();
  715. pRenderContext->AntiAliasingHint( AA_HINT_MESHES );
  716. }
  717. // FIXME: Disable material system threading, to better emulate how regular screenshots are made.
  718. // The API requires us to know the nMaterialSystemThread index, which is only available in engine, and I don't
  719. // want to modify IMaterialSystem just to get savegame screenshots to work. Find another way.
  720. int nMaterialSystemThread = 0;
  721. if ( CommandLine()->FindParm( "-swapcores" ) && !IsPS3() )
  722. {
  723. nMaterialSystemThread = 1;
  724. }
  725. bool bThreadingEnabled = materials->AllowThreading( false, nMaterialSystemThread );
  726. // get the data from the backbuffer and save to disk
  727. // bitmap bits
  728. unsigned char *pImage = ( unsigned char * )malloc( width * 3 * height );
  729. {
  730. CMatRenderContextPtr pRenderContext( materials );
  731. // Get Bits from the material system
  732. pRenderContext->ReadPixels( 0, 0, width, height, pImage, IMAGE_FORMAT_RGB888 );
  733. }
  734. materials->AllowThreading( bThreadingEnabled, nMaterialSystemThread );
  735. // allocate a buffer to write the tga into
  736. int iMaxTGASize = 1024 + (width * height * 4);
  737. void *pTGA = malloc( iMaxTGASize );
  738. CUtlBuffer buffer( pTGA, iMaxTGASize );
  739. if( !TGAWriter::WriteToBuffer( pImage, buffer, width, height, IMAGE_FORMAT_RGB888, IMAGE_FORMAT_RGB888 ) )
  740. {
  741. Error( "Couldn't write bitmap data snapshot.\n" );
  742. }
  743. free( pImage );
  744. // async write to disk (this will take ownership of the memory)
  745. char szPathedFileName[_MAX_PATH];
  746. if ( !IsGameConsole() )
  747. {
  748. Q_snprintf( szPathedFileName, sizeof(szPathedFileName), "//MOD/%s", pFilename );
  749. }
  750. filesystem->AsyncWrite( !IsGameConsole() ? szPathedFileName : pFilename, buffer.Base(), buffer.TellPut(), true );
  751. g_bRenderingScreenshot = false;
  752. m_bAllowViewAccess = false;
  753. }
  754. //-----------------------------------------------------------------------------
  755. // Purpose: takes a screenshot of the save game
  756. //-----------------------------------------------------------------------------
  757. void CViewRender::WriteSaveGameScreenshot( const char *pFilename )
  758. {
  759. WriteSaveGameScreenshotOfSize( pFilename, SAVEGAME_SCREENSHOT_WIDTH, SAVEGAME_SCREENSHOT_HEIGHT );
  760. }
  761. float ScaleFOVByWidthRatio( float fovDegrees, float ratio )
  762. {
  763. float halfAngleRadians = fovDegrees * ( 0.5f * M_PI / 180.0f );
  764. float t = tan( halfAngleRadians );
  765. t *= ratio;
  766. float retDegrees = ( 180.0f / M_PI ) * atan( t );
  767. return retDegrees * 2.0f;
  768. }
  769. //-----------------------------------------------------------------------------
  770. // Purpose: Sets view parameters for level overview mode
  771. // Input : *rect -
  772. //-----------------------------------------------------------------------------
  773. void CViewRender::SetUpOverView()
  774. {
  775. static int oldCRC = 0;
  776. GetView().m_bOrtho = true;
  777. float aspect = (float)GetView().width/(float)GetView().height;
  778. int size_y = 0;
  779. if( cl_leveloverview.GetInt() < 0 )
  780. {
  781. // Fit the level into ortho view bounds
  782. float fWorldWidth = GetClientWorldEntity()->m_WorldMaxs.x - GetClientWorldEntity()->m_WorldMins.x;
  783. float fWorldHeight = GetClientWorldEntity()->m_WorldMaxs.y - GetClientWorldEntity()->m_WorldMins.y;
  784. if( fWorldWidth / aspect < fWorldHeight )
  785. {
  786. size_y = 1.05f * fWorldHeight;
  787. }
  788. else
  789. {
  790. size_y = ( 1.05f * fWorldWidth ) / aspect;
  791. if( size_y < fWorldHeight )
  792. {
  793. Msg("Bad news bears!\n");
  794. }
  795. }
  796. GetView().origin.x = GetClientWorldEntity()->m_WorldMins.x + fWorldWidth / 2;
  797. GetView().origin.y = GetClientWorldEntity()->m_WorldMins.y + fWorldHeight / 2;
  798. GetView().origin.z = GetClientWorldEntity()->GetAbsOrigin().z + GetClientWorldEntity()->m_WorldMaxs.z;
  799. }
  800. else
  801. {
  802. size_y = 1024.0f * cl_leveloverview.GetFloat(); // scale factor, 1024 = OVERVIEW_MAP_SIZE
  803. }
  804. int size_x = size_y * aspect; // standard screen aspect
  805. GetView().origin.x -= size_x / 2;
  806. GetView().origin.y += size_y / 2;
  807. GetView().m_OrthoLeft = 0;
  808. GetView().m_OrthoTop = -size_y;
  809. GetView().m_OrthoRight = size_x;
  810. GetView().m_OrthoBottom = 0;
  811. GetView().angles = QAngle( 90, 90, 0 );
  812. // simple movement detector, show position if moved
  813. int newCRC = GetView().origin.x + GetView().origin.y + GetView().origin.z;
  814. if ( newCRC != oldCRC )
  815. {
  816. Msg( "Overview: scale %.2f, pos_x %.0f, pos_y %.0f\n", cl_leveloverview.GetFloat(),
  817. GetView().origin.x, GetView().origin.y );
  818. oldCRC = newCRC;
  819. }
  820. CMatRenderContextPtr pRenderContext( materials );
  821. pRenderContext->ClearColor4ub( 0, 255, 0, 255 );
  822. // render->DrawTopView( true );
  823. }
  824. void CViewRender::SetUpChaseOverview()
  825. {
  826. // C_BasePlayer *pPlayer = UTIL_PlayerByIndex( m_iTarget1 );
  827. //
  828. // if ( !pPlayer )
  829. // return;
  830. // GetView().origin = m_vCamOrigin;
  831. // GetView().angles = m_aCamAngle;
  832. // GetView().fov = m_flFOV;
  833. float flTransTime = 1.0f;
  834. if ( m_flNextIdealOverviewScaleUpdate < gpGlobals->curtime )
  835. {
  836. m_flOldChaseOverviewScale = m_flIdealChaseOverviewScale;
  837. m_flIdealChaseOverviewScale = HLTVCamera()->GetIdealOverviewScale();
  838. m_flNextIdealOverviewScaleUpdate = gpGlobals->curtime + flTransTime;
  839. }
  840. float flInterp = clamp( ( gpGlobals->curtime - (m_flNextIdealOverviewScaleUpdate - flTransTime) ) / flTransTime, 0.0f, 1.0f );
  841. float flScale = m_flOldChaseOverviewScale + ((m_flIdealChaseOverviewScale-m_flOldChaseOverviewScale) * flInterp);
  842. GetView().m_bOrtho = true;
  843. float aspect = (float)GetView().width/(float)GetView().height;
  844. int size_y = 1024.0f * flScale; // scale factor, 1024 = OVERVIEW_MAP_SIZE
  845. int size_x = size_y * aspect; // standard screen aspect
  846. GetView().origin.x -= size_x / 2;
  847. GetView().origin.y += size_y / 2;
  848. GetView().angles = QAngle( 90, 90, 0 );
  849. GetView().m_OrthoLeft = 0;
  850. GetView().m_OrthoTop = -size_y;
  851. GetView().m_OrthoRight = size_x;
  852. GetView().m_OrthoBottom = 0;
  853. CMatRenderContextPtr pRenderContext( materials );
  854. pRenderContext->ClearColor4ub( 0, 255, 0, 255 );
  855. }
  856. //-----------------------------------------------------------------------------
  857. // Purpose: Render current view into specified rectangle
  858. // Input : *rect -
  859. //-----------------------------------------------------------------------------
  860. ConVar ss_debug_draw_player( "ss_debug_draw_player", "-1", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY );
  861. void CViewRender::Render( vrect_t *rect )
  862. {
  863. VPROF_BUDGET( "CViewRender::Render", "CViewRender::Render" );
  864. m_bAllowViewAccess = true;
  865. CUtlVector< vgui::Panel * > roots;
  866. VGui_GetPanelList( roots );
  867. // Stub out the material system if necessary.
  868. CMatStubHandler matStub;
  869. engine->EngineStats_BeginFrame();
  870. // Assume normal vis
  871. m_bForceNoVis = false;
  872. float flViewportScale = mat_viewportscale.GetFloat();
  873. vrect_t engineRect = *rect;
  874. // The tool framework wants to adjust the entire 3d viewport, not the per-split screen one from below
  875. ToolFramework_AdjustEngineViewport( engineRect.x, engineRect.y, engineRect.width, engineRect.height );
  876. IterateRemoteSplitScreenViewSlots_Push( true );
  877. FOR_EACH_VALID_SPLITSCREEN_PLAYER( hh )
  878. {
  879. ACTIVE_SPLITSCREEN_PLAYER_GUARD_VGUI( hh );
  880. CViewSetup &view = GetView( hh );
  881. float engineAspectRatio = engine->GetScreenAspectRatio( view.width, view.height );
  882. Assert( s_DbgSetupOrigin[ hh ] == view.origin );
  883. Assert( s_DbgSetupAngles[ hh ] == view.angles );
  884. // Using this API gives us a chance to "inset" the 3d views as needed for splitscreen
  885. int insetX, insetY;
  886. VGui_GetEngineRenderBounds( hh, view.x, view.y, view.width, view.height, insetX, insetY );
  887. float aspectRatio = engineAspectRatio * 0.75f; // / (4/3)
  888. view.fov = ScaleFOVByWidthRatio( view.fov, aspectRatio );
  889. view.fovViewmodel = ScaleFOVByWidthRatio( view.fovViewmodel, aspectRatio );
  890. // Let the client mode hook stuff.
  891. GetClientMode()->PreRender( &view );
  892. GetClientMode()->AdjustEngineViewport( view.x, view.y, view.width, view.height );
  893. view.m_nUnscaledX = view.x;
  894. view.m_nUnscaledY = view.y;
  895. view.m_nUnscaledWidth = view.width;
  896. view.m_nUnscaledHeight = view.height;
  897. view.width *= flViewportScale;
  898. view.height *= flViewportScale;
  899. if ( IsGameConsole() )
  900. {
  901. // view must be compliant to resolve restrictions
  902. view.width = AlignValue( view.width, GPU_RESOLVE_ALIGNMENT );
  903. view.height = AlignValue( view.height, GPU_RESOLVE_ALIGNMENT );
  904. }
  905. view.m_flAspectRatio = ( engineAspectRatio > 0.0f ) ? engineAspectRatio : ( (float)view.width / (float)view.height );
  906. int nClearFlags = VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL;
  907. if ( gl_clear_randomcolor.GetBool() )
  908. {
  909. CMatRenderContextPtr pRenderContext( materials );
  910. pRenderContext->ClearColor3ub( RandomInt(0, 255), RandomInt(0, 255), RandomInt(0, 255) );
  911. pRenderContext->ClearBuffers( true, false, false );
  912. pRenderContext->Release();
  913. }
  914. else if ( gl_clear.GetBool() )
  915. {
  916. nClearFlags |= VIEW_CLEAR_COLOR;
  917. }
  918. // Determine if we should draw view model ( client mode override )
  919. bool drawViewModel = GetClientMode()->ShouldDrawViewModel();
  920. // Apply any player specific overrides
  921. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  922. if ( pPlayer )
  923. {
  924. // Override view model if necessary
  925. if ( !pPlayer->m_Local.m_bDrawViewmodel )
  926. {
  927. drawViewModel = false;
  928. }
  929. }
  930. if ( cl_leveloverview.GetInt() != 0 || input->CAM_IsThirdPersonOverview() )
  931. {
  932. if ( cl_leveloverview.GetInt() != 0 )
  933. SetUpOverView();
  934. else
  935. SetUpChaseOverview();
  936. nClearFlags |= VIEW_CLEAR_COLOR;
  937. drawViewModel = false;
  938. }
  939. render->SetMainView( view.origin, view.angles );
  940. int flags = (pPlayer == NULL) ? 0 : RENDERVIEW_DRAWHUD;
  941. if ( drawViewModel )
  942. {
  943. flags |= RENDERVIEW_DRAWVIEWMODEL;
  944. }
  945. // This is the hook for per-split screen player views
  946. C_BaseEntity::PreRenderEntities( hh );
  947. if ( ( ss_debug_draw_player.GetInt() < 0 ) || ( hh == ss_debug_draw_player.GetInt() ) )
  948. {
  949. CViewSetup hudViewSetup;
  950. VGui_GetHudBounds( hh, hudViewSetup.x, hudViewSetup.y, hudViewSetup.width, hudViewSetup.height );
  951. RenderView( view, hudViewSetup, nClearFlags, flags );
  952. }
  953. GetClientMode()->PostRender();
  954. }
  955. IterateRemoteSplitScreenViewSlots_Pop();
  956. engine->EngineStats_EndFrame();
  957. #if !defined( _GAMECONSOLE )
  958. // Stop stubbing the material system so we can see the budget panel
  959. matStub.End();
  960. #endif
  961. // Render the new-style embedded UI
  962. // TODO: when embedded UI will be used for HUD, we will need it to maintain
  963. // a separate screen for HUD and a separate screen stack for pause menu & main menu.
  964. // for now only render embedded UI in pause menu & main menu
  965. #if defined( GAMEUI_UISYSTEM2_ENABLED ) && 0
  966. BaseModUI::CBaseModPanel *pBaseModPanel = BaseModUI::CBaseModPanel::GetSingletonPtr();
  967. // render the new-style embedded UI only if base mod panel is not visible (game-hud)
  968. // otherwise base mod panel will render the embedded UI on top of video/productscreen
  969. if ( !pBaseModPanel || !pBaseModPanel->IsVisible() )
  970. {
  971. Rect_t uiViewport;
  972. uiViewport.x = rect->x;
  973. uiViewport.y = rect->y;
  974. uiViewport.width = rect->width;
  975. uiViewport.height = rect->height;
  976. g_pGameUIGameSystem->Render( uiViewport, gpGlobals->curtime );
  977. }
  978. #endif
  979. // Draw all of the UI stuff "fullscreen"
  980. if ( true ) // For PIXEVENT
  981. {
  982. #if defined( INCLUDE_SCALEFORM )
  983. // Render Scaleform after game and HUD, but before VGui
  984. {
  985. CMatRenderContextPtr pRenderContext( materials );
  986. #if PIX_ENABLE
  987. {
  988. PIXEVENT( pRenderContext, "Scaleform UI" );
  989. }
  990. #endif
  991. pRenderContext->SetScaleformSlotViewport( SF_FULL_SCREEN_SLOT, rect->x, rect->y, rect->width, rect->height );
  992. pRenderContext->AdvanceAndRenderScaleformSlot( SF_FULL_SCREEN_SLOT );
  993. pRenderContext->Flush();
  994. pRenderContext.SafeRelease();
  995. }
  996. #endif
  997. {
  998. CMatRenderContextPtr pRenderContext( materials );
  999. #if PIX_ENABLE
  1000. {
  1001. PIXEVENT( pRenderContext, "VGui UI" );
  1002. }
  1003. #endif
  1004. CViewSetup view2d;
  1005. view2d.x = rect->x;
  1006. view2d.y = rect->y;
  1007. view2d.width = rect->width;
  1008. view2d.height = rect->height;
  1009. render->Push2DView( pRenderContext, view2d, 0, NULL, GetFrustum() );
  1010. render->VGui_Paint( PAINT_UIPANELS );
  1011. {
  1012. // The engine here is trying to access CurrentView() etc. which is bogus
  1013. ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
  1014. render->PopView( pRenderContext, GetFrustum() );
  1015. }
  1016. pRenderContext->Flush();
  1017. pRenderContext.SafeRelease();
  1018. }
  1019. #if defined( INCLUDE_SCALEFORM )
  1020. // Render Scaleform cursor after VGui
  1021. {
  1022. CMatRenderContextPtr pRenderContext( materials );
  1023. #if PIX_ENABLE
  1024. {
  1025. PIXEVENT( pRenderContext, "Scaleform Cursor UI" );
  1026. }
  1027. #endif
  1028. pRenderContext->SetScaleformCursorViewport( rect->x, rect->y, rect->width, rect->height );
  1029. pRenderContext->AdvanceAndRenderScaleformCursor();
  1030. pRenderContext->Flush();
  1031. pRenderContext.SafeRelease();
  1032. }
  1033. #endif
  1034. }
  1035. m_bAllowViewAccess = false;
  1036. }
  1037. static void GetPos( const CCommand &args, Vector &vecOrigin, QAngle &angles )
  1038. {
  1039. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  1040. vecOrigin = MainViewOrigin(nSlot);
  1041. angles = MainViewAngles(nSlot);
  1042. if ( ( args.ArgC() == 2 && atoi( args[1] ) == 2 ) || FStrEq( args[0], "getpos_exact" ) )
  1043. {
  1044. C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
  1045. if ( pPlayer )
  1046. {
  1047. vecOrigin = pPlayer->GetAbsOrigin();
  1048. angles = pPlayer->GetAbsAngles();
  1049. }
  1050. }
  1051. }
  1052. CON_COMMAND( spec_pos, "dump position and angles to the console" )
  1053. {
  1054. Vector vecOrigin;
  1055. QAngle angles;
  1056. GetPos( args, vecOrigin, angles );
  1057. Warning( "%.1f %.1f %.1f %.1f %.1f\n", vecOrigin.x, vecOrigin.y,
  1058. vecOrigin.z, angles.x, angles.y );
  1059. }
  1060. CON_COMMAND( getpos, "dump position and angles to the console" )
  1061. {
  1062. Vector vecOrigin;
  1063. QAngle angles;
  1064. GetPos( args, vecOrigin, angles );
  1065. const char *pCommand1 = "setpos";
  1066. const char *pCommand2 = "setang";
  1067. if ( ( args.ArgC() == 2 && atoi( args[1] ) == 2 ) || FStrEq( args[0], "getpos_exact" ) )
  1068. {
  1069. pCommand1 = "setpos_exact";
  1070. pCommand2 = "setang_exact";
  1071. }
  1072. Warning( "%s %f %f %f;", pCommand1, vecOrigin.x, vecOrigin.y, vecOrigin.z );
  1073. Warning( "%s %f %f %f\n", pCommand2, angles.x, angles.y, angles.z );
  1074. }
  1075. ConCommand getpos_exact( "getpos_exact", getpos, "dump origin and angles to the console" );
  1076. static void PlayDistance_Callback( IConVar *pConVar, const char *pOldString, float flOldValue )
  1077. {
  1078. // diabled for now, reenable if we have specific things we need to change for "play distance"
  1079. /*
  1080. ConVarRef var( pConVar );
  1081. if ( var.GetFloat() == 1 )
  1082. {
  1083. // 2ft
  1084. ConVarRef m_hudscaling( "hud_scaling" );
  1085. m_hudscaling.SetValue( 0.75f );
  1086. ConVarRef m_vmfov( "viewmodel_fov" );
  1087. m_vmfov.SetValue( 60 );
  1088. ConVarRef m_vmoffsetx( "viewmodel_offset_x" );
  1089. m_vmoffsetx.SetValue( 1 );
  1090. ConVarRef m_vmoffsety( "viewmodel_offset_y" );
  1091. m_vmoffsety.SetValue( 1 );
  1092. ConVarRef m_vmoffsetz( "viewmodel_offset_z" );
  1093. m_vmoffsetz.SetValue( -1 );
  1094. }
  1095. else if ( var.GetFloat() == 2 )
  1096. {
  1097. //10ft
  1098. ConVarRef m_hudscaling( "hud_scaling" );
  1099. m_hudscaling.SetValue( 1.0f );
  1100. ConVarRef m_vmfov( "viewmodel_fov" );
  1101. m_vmfov.SetValue( 54 );
  1102. ConVarRef m_vmoffsetx( "viewmodel_offset_x" );
  1103. m_vmoffsetx.SetValue( 0 );
  1104. ConVarRef m_vmoffsety( "viewmodel_offset_y" );
  1105. m_vmoffsety.SetValue( 0 );
  1106. ConVarRef m_vmoffsetz( "viewmodel_offset_z" );
  1107. m_vmoffsetz.SetValue( 0 );
  1108. }
  1109. else
  1110. {
  1111. Warning( "Valid options: 1 = 2ft, 2 = 10ft.\n" );
  1112. }
  1113. */
  1114. }
  1115. static ConVar play_distance( "play_distance", IsGameConsole() ? "2" : "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE, "Set to 1:\"2 foot\" or 2:\"10 foot\" presets.", PlayDistance_Callback );
  1116. /*
  1117. static void HudPresetSize_Callback( IConVar *pConVar, const char *pOldString, float flOldValue )
  1118. {
  1119. ConVarRef var( pConVar );
  1120. if ( var.GetFloat() == 1 )
  1121. {
  1122. // 2ft
  1123. ConVarRef m_hudscaling( "hud_scaling" );
  1124. m_hudscaling.SetValue( 0.75f );
  1125. }
  1126. else if ( var.GetFloat() == 2 )
  1127. {
  1128. //10ft
  1129. ConVarRef m_hudscaling( "hud_scaling" );
  1130. m_hudscaling.SetValue( 0.85f );
  1131. }
  1132. else if ( var.GetFloat() == 3 )
  1133. {
  1134. //10ft
  1135. ConVarRef m_hudscaling( "hud_scaling" );
  1136. m_hudscaling.SetValue( 1.0f );
  1137. }
  1138. else
  1139. {
  1140. Warning( "Valid options: 1 = 2ft, 2 = 10ft.\n" );
  1141. }
  1142. }
  1143. static ConVar play_distance( "play_distance", "2", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE, "1:\"Small\", 2:\"Medium\", 3:\"Couch\" ", HudPresetSize_Callback );
  1144. */
  1145. static void ViewmodelPresetPos_Callback( IConVar *pConVar, const char *pOldString, float flOldValue )
  1146. {
  1147. ConVarRef var( pConVar );
  1148. if ( var.GetFloat() == 1 )
  1149. {
  1150. ConVarRef m_vmfov( "viewmodel_fov" );
  1151. m_vmfov.SetValue( 60 );
  1152. ConVarRef m_vmoffsetx( "viewmodel_offset_x" );
  1153. m_vmoffsetx.SetValue( 1 );
  1154. ConVarRef m_vmoffsety( "viewmodel_offset_y" );
  1155. m_vmoffsety.SetValue( 1 );
  1156. ConVarRef m_vmoffsetz( "viewmodel_offset_z" );
  1157. m_vmoffsetz.SetValue( -1 );
  1158. }
  1159. else if ( var.GetFloat() == 2 )
  1160. {
  1161. ConVarRef m_vmfov( "viewmodel_fov" );
  1162. m_vmfov.SetValue( 54 );
  1163. ConVarRef m_vmoffsetx( "viewmodel_offset_x" );
  1164. m_vmoffsetx.SetValue( 0 );
  1165. ConVarRef m_vmoffsety( "viewmodel_offset_y" );
  1166. m_vmoffsety.SetValue( 0 );
  1167. ConVarRef m_vmoffsetz( "viewmodel_offset_z" );
  1168. m_vmoffsetz.SetValue( 0 );
  1169. }
  1170. else if ( var.GetFloat() == 3 )
  1171. {
  1172. ConVarRef m_vmfov( "viewmodel_fov" );
  1173. m_vmfov.SetValue( 68 );
  1174. ConVarRef m_vmoffsetx( "viewmodel_offset_x" );
  1175. m_vmoffsetx.SetValue( 2.5f );
  1176. ConVarRef m_vmoffsety( "viewmodel_offset_y" );
  1177. m_vmoffsety.SetValue( 0 );
  1178. ConVarRef m_vmoffsetz( "viewmodel_offset_z" );
  1179. m_vmoffsetz.SetValue( -1.5f );
  1180. }
  1181. else
  1182. {
  1183. Warning( "Valid options: 1 = Desktop, 2 = Couch, 3 = Classic.\n" );
  1184. }
  1185. }
  1186. static ConVar viewmodel_presetpos( "viewmodel_presetpos", "1", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE, "1:\"Desktop\", 2:\"Couch\", 3:\"Classic\" ", ViewmodelPresetPos_Callback );