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.

1127 lines
30 KiB

  1. //====== Copyright � 1996-2005, Valve Corporation, All rights reserved. =======
  2. //
  3. // Purpose: Implmentation of IEngineTool callback interface
  4. // Tool .dlls can call back through this interface to talk to the engine
  5. //
  6. //=============================================================================
  7. #include "ienginetoolinternal.h"
  8. #include "EngineSoundInternal.h"
  9. #include "vengineserver_impl.h"
  10. #include "cdll_engine_int.h"
  11. #include "toolframework/ienginetool.h"
  12. #include "client.h"
  13. #include "server.h"
  14. #include "con_nprint.h"
  15. #include "toolframework/itoolframework.h"
  16. #include "sound.h"
  17. #include "screen.h"
  18. #include "render.h"
  19. #include "gl_matsysiface.h"
  20. #include "cl_main.h"
  21. #include "sys_dll.h"
  22. #include "ivideomode.h"
  23. #include "voice.h"
  24. #include "filesystem_engine.h"
  25. #include "enginetrace.h"
  26. #include "Overlay.h"
  27. #include "r_efx.h"
  28. #include "r_local.h"
  29. #include "lightcache.h"
  30. #include "ispatialpartitioninternal.h"
  31. #include "networkstringtableserver.h"
  32. #include "networkstringtable.h"
  33. #include "igame.h"
  34. #include "gl_rmain.h"
  35. #ifndef DEDICATED
  36. #include "vgui_baseui_interface.h"
  37. #endif
  38. // NOTE: This has to be the last file included!
  39. #include "tier0/memdbgon.h"
  40. // External variables and APIs needed
  41. extern CSysModule *g_GameDLL;
  42. extern ConVar host_timescale;
  43. extern CGlobalVars g_ServerGlobalVariables;
  44. void SV_ForceSend();
  45. CreateInterfaceFn ClientDLL_GetFactory( void );
  46. extern CNetworkStringTableContainer *networkStringTableContainerServer;
  47. IOverlayMgr *OverlayMgr();
  48. void SV_ForceSend();
  49. extern ConVar host_framerate;
  50. void CL_StartMovie( const char *filename, int flags, int nWidth, int nHeight, float flFrameRate, int jpeg_quality );
  51. void CL_EndMovie();
  52. bool CL_IsRecordingMovie();
  53. void VGui_SetGameDLLPanelsVisible( bool show );
  54. float AudioSource_GetSoundDuration( char const *pName );
  55. //-----------------------------------------------------------------------------
  56. // Purpose: Singleton implementation of external tools callback interface
  57. //-----------------------------------------------------------------------------
  58. class CEngineTool : public IEngineToolInternal
  59. {
  60. public:
  61. CEngineTool();
  62. // Methods of IEngineToolFramework
  63. // Take over input
  64. virtual void ShowCursor( bool show );
  65. virtual bool IsCursorVisible() const;
  66. // Helpers for implementing a tool switching UI
  67. virtual int GetToolCount() const;
  68. virtual const char *GetToolName( int index ) const;
  69. virtual void SwitchToTool( int index );
  70. virtual bool IsTopmostTool( const IToolSystem *sys ) const;
  71. virtual const IToolSystem *GetToolSystem( int index ) const;
  72. virtual IToolSystem *GetTopmostTool();
  73. // If module not already loaded, loads it and optionally switches to first tool in module. Returns false if load failed or tool already loaded
  74. virtual bool LoadToolModule( char const *pToolModule, bool bSwitchToFirst );
  75. public:
  76. // Retrieve factories from server.dll and client.dll to get at specific interfaces defined within
  77. virtual void GetServerFactory( CreateInterfaceFn& factory );
  78. virtual void GetClientFactory( CreateInterfaceFn& factory );
  79. // Issue a console command
  80. virtual void Command( const char *cmd );
  81. // Flush console command buffer right away
  82. virtual void Execute();
  83. // If in a level, get name of current level
  84. virtual const char *GetCurrentMap();
  85. virtual void ChangeToMap( const char *mapname );
  86. virtual bool IsMapValid( const char *mapname );
  87. // Method for causing engine to call client to render scene with no view model or overlays
  88. virtual void RenderView( CViewSetup &view, int nFlags, int nWhatToRender );
  89. // Returns true if the player is fully connected and active in game (i.e, not still loading)
  90. virtual bool IsInGame();
  91. // Returns true if the player is connected, but not necessarily active in game (could still be loading)
  92. virtual bool IsConnected();
  93. virtual int GetMaxClients(); // Tools might want to ensure single player, e.g.
  94. virtual bool IsGamePaused();
  95. virtual void SetGamePaused( bool paused );
  96. virtual float GetTimescale(); // host_timescale ConVar multiplied by the game timescale
  97. virtual void SetTimescale( float scale );
  98. // Real time is unscaled, but is updated once per frame
  99. virtual float GetRealTime();
  100. virtual float GetRealFrameTime(); // unscaled
  101. virtual float Time(); // Get high precision timer (for profiling?)
  102. // Host time is scaled
  103. virtual float HostFrameTime(); // host_frametime
  104. virtual float HostTime(); // host_time
  105. virtual int HostTick(); // host_tickcount
  106. virtual int HostFrameCount(); // total famecount
  107. virtual float ServerTime(); // gpGlobals->curtime on server
  108. virtual float ServerFrameTime(); // gpGlobals->frametime on server
  109. virtual int ServerTick(); // gpGlobals->tickcount on server
  110. virtual float ServerTickInterval(); // tick interval on server
  111. virtual float ClientTime(); // gpGlobals->curtime on client
  112. virtual float ClientFrameTime(); // gpGlobals->frametime on client
  113. virtual int ClientTick(); // gpGlobals->tickcount on client
  114. virtual void SetClientFrameTime( float frametime ); // gpGlobals->frametime on client
  115. // Currently the engine doesn't like to do networking when it's paused, but if a tool changes entity state, it can be useful to force
  116. // a network update to get that state over to the client
  117. virtual void ForceUpdateDuringPause();
  118. // Maybe through modelcache???
  119. virtual model_t *GetModel( HTOOLHANDLE hEntity );
  120. // Get the .mdl file used by entity (if it's a cbaseanimating)
  121. virtual studiohdr_t *GetStudioModel( HTOOLHANDLE hEntity );
  122. // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this)
  123. // Prints the formatted string to the notification area of the screen ( down the right hand edge
  124. // numbered lines starting at position 0
  125. virtual void Con_NPrintf( int pos, const char *fmt, ... );
  126. // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this)
  127. // Similar to Con_NPrintf, but allows specifying custom text color and duration information
  128. virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... );
  129. // Get the current game directory (hl2, tf2, hl1, cstrike, etc.)
  130. virtual void GetGameDir( char *szGetGameDir, int maxlength );
  131. // Do we need separate rects for the 3d "viewport" vs. the tools surface??? and can we control viewports from
  132. virtual void GetScreenSize( int& width, int &height );
  133. virtual int StartSound(
  134. int iUserData,
  135. bool staticsound,
  136. int iEntIndex,
  137. int iChannel,
  138. const char *pSample,
  139. float flVolume,
  140. soundlevel_t iSoundlevel,
  141. const Vector& origin,
  142. const Vector& direction,
  143. int iFlags = 0,
  144. int iPitch = PITCH_NORM,
  145. bool bUpdatePositions = true,
  146. float delay = 0.0f,
  147. int speakerentity = -1 );
  148. virtual void StopSoundByGuid( int guid );
  149. virtual void SetVolumeByGuid( int guid, float flVolume );
  150. virtual bool IsSoundStillPlaying( int guid );
  151. virtual bool GetSoundChannelVolume( const char* sound, float &flVolumeLeft, float &flVolumeRight ) { return false; }
  152. virtual float GetSoundDuration( int guid );
  153. virtual void ReloadSound( const char *pSample );
  154. virtual void StopAllSounds( );
  155. virtual void SetAudioState( const AudioState_t &audioState );
  156. virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles );
  157. virtual bool GetPlayerView( CViewSetup &playerView, int x, int y, int w, int h );
  158. virtual void CreatePickingRay( const CViewSetup &viewSetup, int x, int y, Vector& org, Vector& forward );
  159. virtual bool IsLoopingSound( int guid );
  160. virtual void InstallQuitHandler( void *pvUserData, FnQuitHandler func );
  161. virtual void TakeTGAScreenShot( const char *filename, int width, int height );
  162. // Even if game is paused, force networking to update to get new server state down to client
  163. virtual void ForceSend();
  164. virtual bool IsRecordingMovie();
  165. // NOTE: Params can contain file name, frame rate, output avi, output raw, and duration
  166. virtual void StartMovieRecording( KeyValues *pMovieParams );
  167. virtual void EndMovieRecording();
  168. virtual void CancelMovieRecording();
  169. virtual AVIHandle_t GetRecordingAVIHandle();
  170. virtual void StartRecordingVoiceToFile( const char *filename, const char *pPathID = 0 );
  171. virtual void StopRecordingVoiceToFile();
  172. virtual bool IsVoiceRecording();
  173. virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace );
  174. virtual void TraceRayServer( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace );
  175. bool CanQuit();
  176. void UpdateScreenshot();
  177. bool ShouldSuppressDeInit() const;
  178. virtual bool IsConsoleVisible();
  179. virtual int GetPointContents( const Vector &vecPosition );
  180. virtual int GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] );
  181. virtual int GetLightingConditions( const Vector &vecPosition, Vector *pColors, int nMaxLocalLights, LightDesc_t *pLocalLights );
  182. // precache methods
  183. virtual bool PrecacheSound( const char *pName, bool bPreload = false );
  184. virtual bool PrecacheModel( const char *pName, bool bPreload = false );
  185. virtual float GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList );
  186. virtual void GetWorldToScreenMatrixForView( const CViewSetup &view, VMatrix *pVMatrix );
  187. virtual SpatialPartitionHandle_t CreatePartitionHandle( IHandleEntity *pEntity, SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs );
  188. virtual void DestroyPartitionHandle( SpatialPartitionHandle_t hPartition );
  189. virtual void InstallPartitionQueryCallback( IPartitionQueryCallback *pQuery );
  190. virtual void RemovePartitionQueryCallback( IPartitionQueryCallback *pQuery );
  191. virtual void ElementMoved( SpatialPartitionHandle_t handle, const Vector& mins, const Vector& maxs );
  192. virtual float GetSoundDuration( const char *pszName );
  193. virtual void ValidateSoundCache( char const *pchSoundName );
  194. virtual void PrefetchSound( char const *pchSoundName );
  195. virtual void* GetEngineHwnd();
  196. virtual void OnModeChanged( bool bGameMode );
  197. public:
  198. // Methods of IEngineToolInternal
  199. virtual void SetIsInGame( bool bIsInGame );
  200. virtual float GetSoundElapsedTime( int guid );
  201. virtual bool GetPreventSound( void );
  202. private:
  203. bool m_bIsInGame;
  204. struct QuitHandler_t
  205. {
  206. void *userdata;
  207. FnQuitHandler func;
  208. };
  209. CUtlVector< QuitHandler_t > m_QuitHandlers;
  210. char m_szScreenshotFile[ MAX_OSPATH ];
  211. int m_nScreenshotWidth;
  212. int m_nScreenshotHeight;
  213. bool m_bRecordingMovie;
  214. bool m_bSuppressDeInit;
  215. char m_szVoiceoverFile[ MAX_OSPATH ];
  216. };
  217. //-----------------------------------------------------------------------------
  218. // Singleton
  219. //-----------------------------------------------------------------------------
  220. static CEngineTool g_EngineTool;
  221. IEngineToolInternal *g_pEngineToolInternal = &g_EngineTool;
  222. void EngineTool_InstallQuitHandler( void *pvUserData, FnQuitHandler func )
  223. {
  224. g_EngineTool.InstallQuitHandler( pvUserData, func );
  225. }
  226. //-----------------------------------------------------------------------------
  227. // Purpose:
  228. // Output : Returns true on success, false on failure.
  229. //-----------------------------------------------------------------------------
  230. bool EngineTool_CheckQuitHandlers()
  231. {
  232. return g_EngineTool.CanQuit();
  233. }
  234. void EngineTool_UpdateScreenshot()
  235. {
  236. g_EngineTool.UpdateScreenshot();
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Constructor
  240. //-----------------------------------------------------------------------------
  241. CEngineTool::CEngineTool()
  242. {
  243. m_bIsInGame = false;
  244. m_szScreenshotFile[ 0 ] = 0;
  245. m_nScreenshotWidth = 180;
  246. m_nScreenshotHeight = 100;
  247. m_bRecordingMovie = false;
  248. m_bSuppressDeInit = false;
  249. m_szVoiceoverFile[ 0 ] = 0;
  250. }
  251. //-----------------------------------------------------------------------------
  252. // Singleton
  253. //-----------------------------------------------------------------------------
  254. void CEngineTool::ShowCursor( bool show )
  255. {
  256. Assert( 0 );
  257. }
  258. bool CEngineTool::IsCursorVisible() const
  259. {
  260. Assert( 0 );
  261. return true;
  262. }
  263. int CEngineTool::GetPointContents( const Vector &vecPosition )
  264. {
  265. return g_pEngineTraceClient->GetPointContents( vecPosition, NULL );
  266. }
  267. int CEngineTool::GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] )
  268. {
  269. return g_pEfx->CL_GetActiveDLights( pList );
  270. }
  271. bool WorldLightToMaterialLight( dworldlight_t* pWorldLight, LightDesc_t& light );
  272. int CEngineTool::GetLightingConditions( const Vector &vecLightingOrigin, Vector *pColors, int nMaxLocalLights, LightDesc_t *pLocalLights )
  273. {
  274. LightcacheGetDynamic_Stats stats;
  275. LightingState_t state;
  276. LightcacheGetDynamic( vecLightingOrigin, state, stats, NULL );
  277. Assert( state.numlights >= 0 && state.numlights < MAXLOCALLIGHTS );
  278. memcpy( pColors, state.r_boxcolor, sizeof(state.r_boxcolor) );
  279. int nLightCount = 0;
  280. for ( int i = 0; i < state.numlights; ++i )
  281. {
  282. LightDesc_t *pLightDesc = &pLocalLights[nLightCount];
  283. if (!WorldLightToMaterialLight( state.locallight[i], *pLightDesc ))
  284. continue;
  285. // Apply lightstyle
  286. float bias = LightStyleValue( state.locallight[i]->style );
  287. // Deal with overbrighting + bias
  288. pLightDesc->m_Color[0] *= bias;
  289. pLightDesc->m_Color[1] *= bias;
  290. pLightDesc->m_Color[2] *= bias;
  291. if ( ++nLightCount >= nMaxLocalLights )
  292. break;
  293. }
  294. return nLightCount;
  295. }
  296. void CEngineTool::GetServerFactory( CreateInterfaceFn& factory )
  297. {
  298. factory = Sys_GetFactory( g_GameDLL );
  299. }
  300. void CEngineTool::GetClientFactory( CreateInterfaceFn& factory )
  301. {
  302. factory = ClientDLL_GetFactory();
  303. }
  304. void CEngineTool::Command( const char *cmd )
  305. {
  306. Cbuf_AddText( Cbuf_GetCurrentPlayer(), cmd );
  307. }
  308. void CEngineTool::Execute()
  309. {
  310. Cbuf_Execute();
  311. }
  312. const char *CEngineTool::GetCurrentMap()
  313. {
  314. if ( sv.IsDedicated() )
  315. return "Dedicated Server";
  316. if ( !GetBaseLocalClient().IsConnected() )
  317. {
  318. if ( sv.IsLoading() )
  319. return sv.GetMapName();
  320. return "";
  321. }
  322. return GetBaseLocalClient().m_szLevelName;
  323. }
  324. void CEngineTool::ChangeToMap( const char *mapname )
  325. {
  326. if ( modelloader->Map_IsValid( mapname ) )
  327. {
  328. Cbuf_AddText( Cbuf_GetCurrentPlayer(), va( "map \"%s\"\n", mapname ) );
  329. }
  330. }
  331. bool CEngineTool::IsMapValid( const char *mapname )
  332. {
  333. return modelloader->Map_IsValid( mapname );
  334. }
  335. // Allows tools to kick off rendering by having the engine call the client
  336. void CEngineTool::RenderView( CViewSetup &view, int nFlags, int whatToRender )
  337. {
  338. // Call client
  339. ACTIVE_SPLITSCREEN_PLAYER_GUARD( 0 );
  340. g_ClientDLL->RenderView( view, nFlags, whatToRender );
  341. }
  342. void CEngineTool::SetIsInGame( bool bIsInGame )
  343. {
  344. m_bIsInGame = bIsInGame;
  345. }
  346. bool CEngineTool::IsInGame()
  347. {
  348. return m_bIsInGame && GetBaseLocalClient().IsConnected();
  349. }
  350. bool CEngineTool::IsConnected()
  351. {
  352. return GetBaseLocalClient().IsConnected();
  353. }
  354. int CEngineTool::GetMaxClients()
  355. {
  356. return GetBaseLocalClient().m_nMaxClients;
  357. }
  358. bool CEngineTool::IsGamePaused()
  359. {
  360. return GetBaseLocalClient().IsPaused();
  361. }
  362. bool CEngineTool::IsConsoleVisible()
  363. {
  364. #ifdef DEDICATED
  365. return false;
  366. #else
  367. return EngineVGui()->IsConsoleVisible();
  368. #endif
  369. }
  370. void CEngineTool::SetGamePaused( bool paused )
  371. {
  372. sv.SetPaused( paused );
  373. }
  374. float CEngineTool::GetTimescale()
  375. {
  376. return host_timescale.GetFloat() * sv.GetTimescale();
  377. }
  378. void CEngineTool::SetTimescale( float scale )
  379. {
  380. host_timescale.SetValue( scale );
  381. }
  382. float CEngineTool::Time()
  383. {
  384. return Plat_FloatTime();
  385. }
  386. // Real time is unscaled, but is updated once per frame
  387. float CEngineTool::GetRealTime()
  388. {
  389. return realtime;
  390. }
  391. float CEngineTool::GetRealFrameTime()
  392. {
  393. return host_frametime_unscaled;
  394. }
  395. float CEngineTool::HostFrameTime()
  396. {
  397. return host_frametime;
  398. }
  399. float CEngineTool::HostTime()
  400. {
  401. return host_time;
  402. }
  403. int CEngineTool::HostTick()
  404. {
  405. return host_tickcount;
  406. }
  407. int CEngineTool::HostFrameCount()
  408. {
  409. return host_framecount;
  410. }
  411. float CEngineTool::ServerTime()
  412. {
  413. return g_ServerGlobalVariables.curtime;
  414. }
  415. float CEngineTool::ServerFrameTime()
  416. {
  417. return g_ServerGlobalVariables.frametime;
  418. }
  419. int CEngineTool::ServerTick()
  420. {
  421. return g_ServerGlobalVariables.tickcount;
  422. }
  423. float CEngineTool::ServerTickInterval()
  424. {
  425. return g_ServerGlobalVariables.interval_per_tick;
  426. }
  427. float CEngineTool::ClientTime()
  428. {
  429. return g_ClientGlobalVariables.curtime;
  430. }
  431. float CEngineTool::ClientFrameTime()
  432. {
  433. return g_ClientGlobalVariables.frametime;
  434. }
  435. int CEngineTool::ClientTick()
  436. {
  437. return g_ClientGlobalVariables.tickcount;
  438. }
  439. void CEngineTool::SetClientFrameTime( float frametime )
  440. {
  441. g_ClientGlobalVariables.frametime = frametime;
  442. }
  443. void CEngineTool::ForceUpdateDuringPause()
  444. {
  445. SV_ForceSend();
  446. }
  447. model_t *CEngineTool::GetModel( HTOOLHANDLE hEntity )
  448. {
  449. Assert( 0 );
  450. return NULL;
  451. }
  452. studiohdr_t *CEngineTool::GetStudioModel( HTOOLHANDLE hEntity )
  453. {
  454. Assert( 0 );
  455. return NULL;
  456. }
  457. void CEngineTool::Con_NPrintf( int pos, const char *fmt, ... )
  458. {
  459. char buf[ 1024 ];
  460. va_list argptr;
  461. va_start( argptr, fmt );
  462. _vsnprintf( buf, sizeof( buf ) - 1, fmt, argptr );
  463. va_end( argptr );
  464. return ::Con_NPrintf( pos, "%s", buf );
  465. }
  466. void CEngineTool::Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... )
  467. {
  468. char buf[ 1024 ];
  469. va_list argptr;
  470. va_start( argptr, fmt );
  471. _vsnprintf( buf, sizeof( buf ) - 1, fmt, argptr );
  472. va_end( argptr );
  473. ::Con_NXPrintf( info, "%s", buf );
  474. }
  475. void CEngineTool::GetGameDir( char *szGetGameDir, int maxlength )
  476. {
  477. Q_strncpy( szGetGameDir, com_gamedir, maxlength );
  478. }
  479. void CEngineTool::GetScreenSize( int& width, int &height )
  480. {
  481. CMatRenderContextPtr pRenderContext( materials );
  482. pRenderContext->GetWindowSize( width, height );
  483. }
  484. //-----------------------------------------------------------------------------
  485. // Purpose: Helpers for implementing a tool switching UI
  486. // Input : -
  487. // Output : int
  488. //-----------------------------------------------------------------------------
  489. int CEngineTool::GetToolCount() const
  490. {
  491. return toolframework->GetToolCount();
  492. }
  493. //-----------------------------------------------------------------------------
  494. // Purpose:
  495. // Input : index -
  496. // Output : char
  497. //-----------------------------------------------------------------------------
  498. const char *CEngineTool::GetToolName( int index ) const
  499. {
  500. return toolframework->GetToolName( index );
  501. }
  502. //-----------------------------------------------------------------------------
  503. // Purpose:
  504. // Input : index -
  505. //-----------------------------------------------------------------------------
  506. void CEngineTool::SwitchToTool( int index )
  507. {
  508. toolframework->SwitchToTool( index );
  509. }
  510. bool CEngineTool::IsTopmostTool( const IToolSystem *sys ) const
  511. {
  512. return toolframework->IsTopmostTool( sys );
  513. }
  514. IToolSystem *CEngineTool::GetTopmostTool()
  515. {
  516. return toolframework->GetTopmostTool();
  517. }
  518. const IToolSystem *CEngineTool::GetToolSystem( int index ) const
  519. {
  520. return toolframework->GetToolSystem( index );
  521. }
  522. // If module not already loaded, loads it and optionally switches to first tool in module. Returns false if load failed or tool already loaded
  523. bool CEngineTool::LoadToolModule( char const *pToolModule, bool bSwitchToFirst )
  524. {
  525. return toolframework->LoadToolModule( pToolModule, bSwitchToFirst );
  526. }
  527. void CEngineTool::ValidateSoundCache( char const *pchSoundName )
  528. {
  529. S_ValidateSoundCache( pchSoundName );
  530. }
  531. void CEngineTool::PrefetchSound( char const *pchSoundName )
  532. {
  533. S_PrefetchSound( pchSoundName, false );
  534. }
  535. int CEngineTool::StartSound(
  536. int iUserData,
  537. bool staticsound,
  538. int iEntIndex,
  539. int iChannel,
  540. const char *pSample,
  541. float flVolume,
  542. soundlevel_t iSoundlevel,
  543. const Vector& origin,
  544. const Vector& direction,
  545. int iFlags /*= 0*/,
  546. int iPitch /*= PITCH_NORM*/,
  547. bool bUpdatePositions /*= true*/,
  548. float delay /*= 0.0f*/,
  549. int speakerentity /*= -1*/ )
  550. {
  551. StartSoundParams_t params;
  552. params.userdata = iUserData;
  553. params.staticsound = staticsound;
  554. params.soundsource = iEntIndex;
  555. params.entchannel = iChannel;
  556. params.pSfx = S_PrecacheSound( pSample );
  557. params.origin = origin;
  558. params.direction = direction;
  559. params.bUpdatePositions = bUpdatePositions;
  560. params.fvol = flVolume;
  561. params.soundlevel = iSoundlevel;
  562. params.flags = iFlags;
  563. params.pitch = iPitch;
  564. params.fromserver = false;
  565. params.delay = delay;
  566. params.speakerentity = speakerentity;
  567. params.bToolSound = true;
  568. int guid = S_StartSound( params );
  569. return guid;
  570. }
  571. void CEngineTool::StopSoundByGuid( int guid )
  572. {
  573. S_StopSoundByGuid( guid );
  574. }
  575. void CEngineTool::SetVolumeByGuid( int guid, float flVolume )
  576. {
  577. S_SetVolumeByGuid( guid, flVolume );
  578. }
  579. bool CEngineTool::IsSoundStillPlaying( int guid )
  580. {
  581. return S_IsSoundStillPlaying( guid );
  582. }
  583. float CEngineTool::GetSoundDuration( int guid )
  584. {
  585. return S_SoundDurationByGuid( guid );
  586. }
  587. float CEngineTool::GetSoundElapsedTime( int guid )
  588. {
  589. return S_GetElapsedTimeByGuid( guid );
  590. }
  591. void* CEngineTool::GetEngineHwnd()
  592. {
  593. return game->GetMainWindow();
  594. }
  595. float CEngineTool::GetSoundDuration( const char *pszName )
  596. {
  597. return AudioSource_GetSoundDuration( pszName );
  598. }
  599. void CEngineTool::ReloadSound( const char *pSample )
  600. {
  601. S_ReloadSound( pSample );
  602. }
  603. void CEngineTool::StopAllSounds( )
  604. {
  605. S_StopAllSounds( true );
  606. }
  607. bool CEngineTool::GetPreventSound( )
  608. {
  609. return S_GetPreventSound( );
  610. }
  611. // Returns if the sound is looping
  612. bool CEngineTool::IsLoopingSound( int guid )
  613. {
  614. return S_IsLoopingSoundByGuid( guid );
  615. }
  616. void CEngineTool::TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace )
  617. {
  618. trace_t tempTrace;
  619. g_pEngineTraceClient->TraceRay( ray, fMask, pTraceFilter, &tempTrace );
  620. memcpy( pTrace, &tempTrace, sizeof ( CBaseTrace ) );
  621. }
  622. void CEngineTool::TraceRayServer( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace )
  623. {
  624. trace_t tempTrace;
  625. g_pEngineTraceServer->TraceRay( ray, fMask, pTraceFilter, &tempTrace );
  626. memcpy( pTrace, &tempTrace, sizeof ( CBaseTrace ) );
  627. }
  628. void CEngineTool::SetAudioState( const AudioState_t &audioState )
  629. {
  630. Host_SetAudioState( audioState );
  631. }
  632. // Sets the location of the main view
  633. void CEngineTool::SetMainView( const Vector &vecOrigin, const QAngle &angles )
  634. {
  635. g_EngineRenderer->SetMainView( vecOrigin, angles );
  636. }
  637. static float ScaleFOVByWidthRatio( float fovDegrees, float ratio )
  638. {
  639. float halfAngleRadians = fovDegrees * ( 0.5f * M_PI / 180.0f );
  640. float t = tan( halfAngleRadians );
  641. t *= ratio;
  642. float retDegrees = ( 180.0f / M_PI ) * atan( t );
  643. return retDegrees * 2.0f;
  644. }
  645. // Gets the player view
  646. bool CEngineTool::GetPlayerView( CViewSetup &viewSetup, int x, int y, int w, int h )
  647. {
  648. if ( g_ClientDLL )
  649. {
  650. if ( !g_ClientDLL->GetPlayerView( viewSetup ) )
  651. return false;
  652. // Initialize view setup given the desired rectangle
  653. viewSetup.x = x;
  654. viewSetup.y = y;
  655. viewSetup.width = w;
  656. viewSetup.height = h;
  657. viewSetup.m_flAspectRatio = (viewSetup.height != 0) ? (float)viewSetup.width / (float)viewSetup.height : 4.0f / 3.0f;
  658. viewSetup.m_bRenderToSubrectOfLargerScreen = true;
  659. viewSetup.fov = ScaleFOVByWidthRatio( viewSetup.fov, viewSetup.m_flAspectRatio / ( 4.0f / 3.0f ) );
  660. viewSetup.fovViewmodel = ScaleFOVByWidthRatio( viewSetup.fovViewmodel, viewSetup.m_flAspectRatio / ( 4.0f / 3.0f ) );
  661. return true;
  662. }
  663. return false;
  664. }
  665. //-----------------------------------------------------------------------------
  666. // From a location on the screen, figure out the vector into the world
  667. //-----------------------------------------------------------------------------
  668. void CEngineTool::CreatePickingRay( const CViewSetup &viewSetup, int x, int y, Vector& org, Vector& forward )
  669. {
  670. // Remap x and y into -1 to 1 normalized space
  671. float xf, yf;
  672. xf = ( 2.0f * (float)x / (float)viewSetup.width ) - 1.0f;
  673. yf = ( 2.0f * (float)y / (float)viewSetup.height ) - 1.0f;
  674. // Flip y axis
  675. yf = -yf;
  676. VMatrix worldToScreen;
  677. GetWorldToScreenMatrixForView( viewSetup, &worldToScreen );
  678. VMatrix screenToWorld;
  679. MatrixInverseGeneral( worldToScreen, screenToWorld );
  680. // Create two points at the normalized mouse x, y pos and at the near and far z planes (0 and 1 depth)
  681. Vector v1, v2;
  682. v1.Init( xf, yf, 0.0f );
  683. v2.Init( xf, yf, 1.0f );
  684. Vector o2;
  685. // Transform the two points by the screen to world matrix
  686. screenToWorld.V3Mul( v1, org ); // ray start origin
  687. screenToWorld.V3Mul( v2, o2 ); // ray end origin
  688. VectorSubtract( o2, org, forward );
  689. forward.NormalizeInPlace();
  690. }
  691. //-----------------------------------------------------------------------------
  692. // Purpose: Returns true if all handlers say we can quit the engine
  693. //-----------------------------------------------------------------------------
  694. bool CEngineTool::CanQuit()
  695. {
  696. int c = m_QuitHandlers.Count();
  697. for ( int i = 0; i < c; ++i )
  698. {
  699. QuitHandler_t& qh = m_QuitHandlers[ i ];
  700. FnQuitHandler func = qh.func;
  701. if ( func )
  702. {
  703. if ( !func( qh.userdata ) )
  704. {
  705. return false;
  706. }
  707. }
  708. }
  709. return true;
  710. }
  711. void CEngineTool::InstallQuitHandler( void *pvUserData, FnQuitHandler func )
  712. {
  713. QuitHandler_t qh;
  714. qh.userdata = pvUserData;
  715. qh.func = func;
  716. m_QuitHandlers.AddToTail( qh );
  717. }
  718. // precache methods
  719. bool CEngineTool::PrecacheSound( const char *pName, bool bPreload )
  720. {
  721. if ( pName && TestSoundChar( pName, CHAR_SENTENCE ) )
  722. return true;
  723. bool bState = networkStringTableContainerServer->Lock( false );
  724. int flags = bPreload ? RES_PRELOAD : 0;
  725. int i = sv.PrecacheSound( pName, flags );
  726. networkStringTableContainerServer->Lock( bState );
  727. return i >= 0;
  728. }
  729. bool CEngineTool::PrecacheModel( const char *pName, bool bPreload )
  730. {
  731. int flags = bPreload ? RES_PRELOAD : 0;
  732. bool bState = networkStringTableContainerServer->Lock( false );
  733. int i = sv.PrecacheModel( pName, flags );
  734. networkStringTableContainerServer->Lock( bState );
  735. return i >= 0;
  736. }
  737. void CEngineTool::TakeTGAScreenShot( const char *filename, int width, int height )
  738. {
  739. Q_strncpy( m_szScreenshotFile, filename, sizeof( m_szScreenshotFile ) );
  740. m_nScreenshotWidth = width;
  741. m_nScreenshotHeight = height;
  742. }
  743. //-----------------------------------------------------------------------------
  744. // Purpose:
  745. //-----------------------------------------------------------------------------
  746. void CEngineTool::UpdateScreenshot()
  747. {
  748. if ( g_LostVideoMemory )
  749. return;
  750. if ( m_szScreenshotFile[0] )
  751. {
  752. g_ClientDLL->WriteSaveGameScreenshotOfSize( m_szScreenshotFile, m_nScreenshotWidth, m_nScreenshotHeight );
  753. m_szScreenshotFile[0] = 0;
  754. }
  755. }
  756. // Even if game is paused, force networking to update to get new server state down to client
  757. void CEngineTool::ForceSend()
  758. {
  759. SV_ForceSend();
  760. }
  761. bool CEngineTool::IsRecordingMovie()
  762. {
  763. if ( m_bRecordingMovie )
  764. {
  765. Assert( CL_IsRecordingMovie() );
  766. return true;
  767. }
  768. return false;
  769. }
  770. // NOTE: Params can contain file name, frame rate, output avi, output raw, and duration
  771. void CEngineTool::StartMovieRecording( KeyValues *pMovieParams )
  772. {
  773. if ( CL_IsRecordingMovie() )
  774. {
  775. Warning( "Can't record movie, already recording!!!\n" );
  776. return;
  777. }
  778. if ( m_bRecordingMovie )
  779. return;
  780. int jpeg_quality = DEFAULT_JPEG_QUALITY;
  781. int flags = 0;
  782. if ( pMovieParams->GetInt( "outputavi", 0 ) )
  783. {
  784. if ( pMovieParams->GetInt( "avisoundonly", 0 ) )
  785. {
  786. flags |= MovieInfo_t::FMOVIE_AVISOUND;
  787. }
  788. else
  789. {
  790. flags |= MovieInfo_t::FMOVIE_AVI | MovieInfo_t::FMOVIE_AVISOUND;
  791. }
  792. }
  793. if ( pMovieParams->GetInt( "outputtga", 0 ) )
  794. {
  795. flags |= MovieInfo_t::FMOVIE_TGA;
  796. }
  797. if ( pMovieParams->GetInt( "outputjpg", 0 ) )
  798. {
  799. flags |= MovieInfo_t::FMOVIE_JPG;
  800. jpeg_quality = pMovieParams->GetInt( "jpeg_quality" );
  801. }
  802. if ( pMovieParams->GetInt( "outputwav", 0 ) )
  803. {
  804. flags |= MovieInfo_t::FMOVIE_WAV;
  805. }
  806. const char *pFileName = pMovieParams->GetString( "filename", NULL );
  807. if ( !pFileName )
  808. {
  809. Warning( "Output filename not specified!\n" );
  810. return;
  811. }
  812. int nWidth = pMovieParams->GetInt( "width", videomode->GetModeWidth() );
  813. int nHeight = pMovieParams->GetInt( "height", videomode->GetModeHeight() );
  814. float flFrameRate = pMovieParams->GetFloat( "framerate", 30.0f );
  815. m_bRecordingMovie = true;
  816. CL_StartMovie( pFileName, flags, nWidth, nHeight, flFrameRate, jpeg_quality );
  817. }
  818. void CEngineTool::EndMovieRecording()
  819. {
  820. if ( !m_bRecordingMovie )
  821. return;
  822. CL_EndMovie();
  823. m_bRecordingMovie = false;
  824. }
  825. void CEngineTool::CancelMovieRecording()
  826. {
  827. EndMovieRecording();
  828. }
  829. AVIHandle_t CEngineTool::GetRecordingAVIHandle()
  830. {
  831. if ( !CL_IsRecordingMovie() )
  832. return AVIHANDLE_INVALID;
  833. return g_hCurrentAVI;
  834. }
  835. bool CEngineTool::ShouldSuppressDeInit() const
  836. {
  837. return m_bSuppressDeInit;
  838. }
  839. void CEngineTool::StartRecordingVoiceToFile( const char *filename, const char *pPathID /*= 0*/ )
  840. {
  841. FileHandle_t fh = g_pFileSystem->Open( filename, "wb", pPathID );
  842. if ( fh != FILESYSTEM_INVALID_HANDLE )
  843. {
  844. byte foo = 'b';
  845. g_pFileSystem->Write( &foo, 1, fh );
  846. g_pFileSystem->Close( fh );
  847. }
  848. g_pFileSystem->RelativePathToFullPath( filename, pPathID, m_szVoiceoverFile, sizeof( m_szVoiceoverFile ) );
  849. g_pFileSystem->RemoveFile( filename, pPathID );
  850. #if !defined( NO_VOICE )
  851. if ( IsVoiceRecording() )
  852. {
  853. Voice_RecordStop();
  854. }
  855. m_bSuppressDeInit = true;
  856. Voice_ForceInit();
  857. Voice_RecordStart( m_szVoiceoverFile, NULL, NULL);
  858. #endif
  859. }
  860. void CEngineTool::StopRecordingVoiceToFile()
  861. {
  862. #if !defined( NO_VOICE )
  863. Voice_RecordStop();
  864. m_bSuppressDeInit = false;
  865. #endif
  866. }
  867. float CEngineTool::GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList )
  868. {
  869. return S_GetMono16Samples( pszName, sampleList );
  870. }
  871. void CEngineTool::GetWorldToScreenMatrixForView( const CViewSetup &view, VMatrix *pVMatrix )
  872. {
  873. VMatrix worldToView, viewToProjection;
  874. view.ComputeViewMatrices( &worldToView, &viewToProjection, pVMatrix );
  875. }
  876. SpatialPartitionHandle_t CEngineTool::CreatePartitionHandle( IHandleEntity *pEntity,
  877. SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs )
  878. {
  879. return SpatialPartition()->CreateHandle( pEntity, listMask, mins, maxs );
  880. }
  881. void CEngineTool::DestroyPartitionHandle( SpatialPartitionHandle_t hPartition )
  882. {
  883. SpatialPartition()->DestroyHandle( hPartition );
  884. }
  885. void CEngineTool::InstallPartitionQueryCallback( IPartitionQueryCallback *pQuery )
  886. {
  887. SpatialPartition()->InstallQueryCallback( pQuery );
  888. }
  889. void CEngineTool::RemovePartitionQueryCallback( IPartitionQueryCallback *pQuery )
  890. {
  891. SpatialPartition()->RemoveQueryCallback( pQuery );
  892. }
  893. void CEngineTool::ElementMoved( SpatialPartitionHandle_t handle, const Vector& mins, const Vector& maxs )
  894. {
  895. SpatialPartition()->ElementMoved( handle, mins, maxs );
  896. }
  897. bool CEngineTool::IsVoiceRecording()
  898. {
  899. #if !defined( NO_VOICE )
  900. return Voice_IsRecording();
  901. #else
  902. return false;
  903. #endif
  904. }
  905. void CEngineTool::OnModeChanged( bool bGameMode )
  906. {
  907. EngineVGui()->OnToolModeChanged( bGameMode );
  908. }
  909. bool EngineTool_SuppressDeInit()
  910. {
  911. return g_EngineTool.ShouldSuppressDeInit();
  912. }
  913. void EngineTool_OverrideSampleRate( int& rate )
  914. {
  915. if ( EngineTool_SuppressDeInit() )
  916. {
  917. rate = 11025;
  918. }
  919. }
  920. // Expose complex interface
  921. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineTool, IEngineTool, VENGINETOOL_INTERFACE_VERSION, g_EngineTool );
  922. // Expose simple interface
  923. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineTool, IEngineToolFramework, VENGINETOOLFRAMEWORK_INTERFACE_VERSION, g_EngineTool );