summaryrefslogtreecommitdiff
path: root/engine/enginetool.cpp
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /engine/enginetool.cpp
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'engine/enginetool.cpp')
-rw-r--r--engine/enginetool.cpp1078
1 files changed, 1078 insertions, 0 deletions
diff --git a/engine/enginetool.cpp b/engine/enginetool.cpp
new file mode 100644
index 0000000..4608387
--- /dev/null
+++ b/engine/enginetool.cpp
@@ -0,0 +1,1078 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implmentation of IEngineTool callback interface
+// Tool .dlls can call back through this interface to talk to the engine
+//
+//=============================================================================
+
+#include "ienginetoolinternal.h"
+#include "EngineSoundInternal.h"
+#include "vengineserver_impl.h"
+#include "cdll_engine_int.h"
+#include "toolframework/ienginetool.h"
+#include "client.h"
+#include "server.h"
+#include "con_nprint.h"
+#include "toolframework/itoolframework.h"
+#include "sound.h"
+#include "screen.h"
+#include "render.h"
+#include "gl_matsysiface.h"
+#include "cl_main.h"
+#include "sys_dll.h"
+#include "ivideomode.h"
+#include "voice.h"
+#include "filesystem_engine.h"
+#include "enginetrace.h"
+#include "Overlay.h"
+#include "r_efx.h"
+#include "r_local.h"
+#include "lightcache.h"
+#include "ispatialpartitioninternal.h"
+#include "networkstringtableserver.h"
+#include "networkstringtable.h"
+#include "gl_rmain.h"
+#include "vprof_telemetry.h"
+
+#ifndef SWDS
+#include "vgui_baseui_interface.h"
+#endif
+
+// External variables and APIs needed
+extern CSysModule *g_GameDLL;
+extern ConVar host_timescale;
+extern CGlobalVars g_ServerGlobalVariables;
+void SV_ForceSend();
+CreateInterfaceFn ClientDLL_GetFactory( void );
+extern CNetworkStringTableContainer *networkStringTableContainerServer;
+
+IOverlayMgr *OverlayMgr();
+
+void SV_ForceSend();
+
+extern ConVar host_framerate;
+
+void VGui_SetGameDLLPanelsVisible( bool show );
+float AudioSource_GetSoundDuration( char const *pName );
+
+//-----------------------------------------------------------------------------
+// Purpose: Singleton implementation of external tools callback interface
+//-----------------------------------------------------------------------------
+class CEngineTool : public IEngineToolInternal
+{
+public:
+ CEngineTool();
+
+ // Methods of IEngineToolFramework
+ // Take over input
+ virtual void ShowCursor( bool show );
+ virtual bool IsCursorVisible() const;
+
+ // Helpers for implementing a tool switching UI
+ virtual int GetToolCount() const;
+ virtual const char *GetToolName( int index ) const;
+ virtual void SwitchToTool( int index );
+
+ virtual bool IsTopmostTool( const IToolSystem *sys ) const;
+ virtual const IToolSystem *GetToolSystem( int index ) const;
+ virtual IToolSystem *GetTopmostTool();
+
+public:
+ // Retrieve factories from server.dll and client.dll to get at specific interfaces defined within
+ virtual void GetServerFactory( CreateInterfaceFn& factory );
+ virtual void GetClientFactory( CreateInterfaceFn& factory );
+
+ // Issue a console command
+ virtual void Command( const char *cmd );
+ // Flush console command buffer right away
+ virtual void Execute();
+
+ // If in a level, get name of current level
+ virtual const char *GetCurrentMap();
+ virtual void ChangeToMap( const char *mapname );
+ virtual bool IsMapValid( const char *mapname );
+
+ // Method for causing engine to call client to render scene with no view model or overlays
+ virtual void RenderView( CViewSetup &view, int nFlags, int nWhatToRender );
+
+ // Returns true if the player is fully connected and active in game (i.e, not still loading)
+ virtual bool IsInGame();
+ // Returns true if the player is connected, but not necessarily active in game (could still be loading)
+ virtual bool IsConnected();
+
+ virtual int GetMaxClients(); // Tools might want to ensure single player, e.g.
+
+ virtual bool IsGamePaused();
+ virtual void SetGamePaused( bool paused );
+
+ virtual float GetTimescale(); // Could do this via ConVar system, too
+ virtual void SetTimescale( float scale );
+
+ // Real time is unscaled, but is updated once per frame
+ virtual float GetRealTime();
+ virtual float GetRealFrameTime(); // unscaled
+
+ virtual float Time(); // Get high precision timer (for profiling?)
+
+ // Host time is scaled
+ virtual float HostFrameTime(); // host_frametime
+ virtual float HostTime(); // host_time
+ virtual int HostTick(); // host_tickcount
+ virtual int HostFrameCount(); // total famecount
+
+ virtual float ServerTime(); // gpGlobals->curtime on server
+ virtual float ServerFrameTime(); // gpGlobals->frametime on server
+ virtual int ServerTick(); // gpGlobals->tickcount on server
+ virtual float ServerTickInterval(); // tick interval on server
+
+ virtual float ClientTime(); // gpGlobals->curtime on client
+ virtual float ClientFrameTime(); // gpGlobals->frametime on client
+ virtual int ClientTick(); // gpGlobals->tickcount on client
+
+ virtual void SetClientFrameTime( float frametime ); // gpGlobals->frametime on client
+
+ // 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
+ // a network update to get that state over to the client
+ virtual void ForceUpdateDuringPause();
+
+ // Maybe through modelcache???
+ virtual model_t *GetModel( HTOOLHANDLE hEntity );
+ // Get the .mdl file used by entity (if it's a cbaseanimating)
+ virtual studiohdr_t *GetStudioModel( HTOOLHANDLE hEntity );
+
+ // SINGLE PLAYER/LISTEN SERVER ONLY (just matching the client .dll api for this)
+ // Prints the formatted string to the notification area of the screen ( down the right hand edge
+ // numbered lines starting at position 0
+ virtual void Con_NPrintf( int pos, const char *fmt, ... );
+ // SINGLE PLAYER/LISTEN SERVER ONLY(just matching the client .dll api for this)
+ // Similar to Con_NPrintf, but allows specifying custom text color and duration information
+ virtual void Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... );
+
+ // Get the current game directory (hl2, tf2, hl1, cstrike, etc.)
+ virtual void GetGameDir( char *szGetGameDir, int maxlength );
+
+// Do we need separate rects for the 3d "viewport" vs. the tools surface??? and can we control viewports from
+ virtual void GetScreenSize( int& width, int &height );
+
+ virtual int StartSound(
+ int iUserData,
+ bool staticsound,
+ int iEntIndex,
+ int iChannel,
+ const char *pSample,
+ float flVolume,
+ soundlevel_t iSoundlevel,
+ const Vector& origin,
+ const Vector& direction,
+ int iFlags = 0,
+ int iPitch = PITCH_NORM,
+ bool bUpdatePositions = true,
+ float delay = 0.0f,
+ int speakerentity = -1 );
+
+ virtual void StopSoundByGuid( int guid );
+ virtual bool IsSoundStillPlaying( int guid );
+ virtual float GetSoundDuration( int guid );
+ virtual void ReloadSound( const char *pSample );
+ virtual void StopAllSounds( );
+ virtual void SetAudioState( const AudioState_t &audioState );
+ virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles );
+ virtual bool GetPlayerView( CViewSetup &playerView, int x, int y, int w, int h );
+ virtual void CreatePickingRay( const CViewSetup &viewSetup, int x, int y, Vector& org, Vector& forward );
+ virtual bool IsLoopingSound( int guid );
+
+ virtual void InstallQuitHandler( void *pvUserData, FnQuitHandler func );
+ virtual void TakeTGAScreenShot( const char *filename, int width, int height );
+ // Even if game is paused, force networking to update to get new server state down to client
+ virtual void ForceSend();
+
+ virtual bool IsRecordingMovie();
+
+ // NOTE: Params can contain file name, frame rate, output avi, output raw, and duration
+ virtual void StartMovieRecording( KeyValues *pMovieParams );
+ virtual void EndMovieRecording();
+ virtual void CancelMovieRecording();
+ virtual IVideoRecorder *GetActiveVideoRecorder();
+
+ virtual void StartRecordingVoiceToFile( const char *filename, const char *pPathID = 0 );
+ virtual void StopRecordingVoiceToFile();
+ virtual bool IsVoiceRecording();
+
+ virtual void TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace );
+ virtual void TraceRayServer( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace );
+
+ bool CanQuit();
+ void UpdateScreenshot();
+
+ bool ShouldSuppressDeInit() const;
+
+ virtual bool IsConsoleVisible();
+ virtual int GetPointContents( const Vector &vecPosition );
+ virtual int GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] );
+ virtual int GetLightingConditions( const Vector &vecPosition, Vector *pColors, int nMaxLocalLights, LightDesc_t *pLocalLights );
+
+ // precache methods
+ virtual bool PrecacheSound( const char *pName, bool bPreload = false );
+ virtual bool PrecacheModel( const char *pName, bool bPreload = false );
+
+ virtual float GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList );
+
+ virtual void GetWorldToScreenMatrixForView( const CViewSetup &view, VMatrix *pVMatrix );
+ virtual SpatialPartitionHandle_t CreatePartitionHandle( IHandleEntity *pEntity, SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs );
+ virtual void DestroyPartitionHandle( SpatialPartitionHandle_t hPartition );
+ virtual void InstallPartitionQueryCallback( IPartitionQueryCallback *pQuery );
+ virtual void RemovePartitionQueryCallback( IPartitionQueryCallback *pQuery );
+ virtual void ElementMoved( SpatialPartitionHandle_t handle, const Vector& mins, const Vector& maxs );
+
+ virtual float GetSoundDuration( const char *pszName );
+
+public:
+ // Methods of IEngineToolInternal
+ virtual void SetIsInGame( bool bIsInGame );
+
+private:
+ bool m_bIsInGame;
+
+ struct QuitHandler_t
+ {
+ void *userdata;
+ FnQuitHandler func;
+ };
+
+ CUtlVector< QuitHandler_t > m_QuitHandlers;
+
+ char m_szScreenshotFile[ MAX_OSPATH ];
+ int m_nScreenshotWidth;
+ int m_nScreenshotHeight;
+
+ bool m_bRecordingMovie;
+ bool m_bSuppressDeInit;
+ char m_szVoiceoverFile[ MAX_OSPATH ];
+};
+
+
+//-----------------------------------------------------------------------------
+// Singleton
+//-----------------------------------------------------------------------------
+static CEngineTool g_EngineTool;
+IEngineToolInternal *g_pEngineToolInternal = &g_EngineTool;
+
+void EngineTool_InstallQuitHandler( void *pvUserData, FnQuitHandler func )
+{
+ g_EngineTool.InstallQuitHandler( pvUserData, func );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool EngineTool_CheckQuitHandlers()
+{
+ return g_EngineTool.CanQuit();
+}
+
+void EngineTool_UpdateScreenshot()
+{
+ g_EngineTool.UpdateScreenshot();
+}
+
+//-----------------------------------------------------------------------------
+// Constructor
+//-----------------------------------------------------------------------------
+CEngineTool::CEngineTool()
+{
+ m_bIsInGame = false;
+ m_szScreenshotFile[ 0 ] = 0;
+ m_nScreenshotWidth = 180;
+ m_nScreenshotHeight = 100;
+
+ m_bRecordingMovie = false;
+ m_bSuppressDeInit = false;
+ m_szVoiceoverFile[ 0 ] = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+// Singleton
+//-----------------------------------------------------------------------------
+void CEngineTool::ShowCursor( bool show )
+{
+ Assert( 0 );
+}
+
+bool CEngineTool::IsCursorVisible() const
+{
+ Assert( 0 );
+ return true;
+}
+
+int CEngineTool::GetPointContents( const Vector &vecPosition )
+{
+ return g_pEngineTraceClient->GetPointContents( vecPosition, NULL );
+}
+
+int CEngineTool::GetActiveDLights( dlight_t *pList[MAX_DLIGHTS] )
+{
+ return g_pEfx->CL_GetActiveDLights( pList );
+}
+
+bool WorldLightToMaterialLight( dworldlight_t* pWorldLight, LightDesc_t& light );
+
+int CEngineTool::GetLightingConditions( const Vector &vecLightingOrigin, Vector *pColors, int nMaxLocalLights, LightDesc_t *pLocalLights )
+{
+ LightcacheGetDynamic_Stats stats;
+ LightingState_t state;
+ LightcacheGetDynamic( vecLightingOrigin, state, stats );
+ Assert( state.numlights >= 0 && state.numlights < MAXLOCALLIGHTS );
+ memcpy( pColors, state.r_boxcolor, sizeof(state.r_boxcolor) );
+
+ int nLightCount = 0;
+ for ( int i = 0; i < state.numlights; ++i )
+ {
+ LightDesc_t *pLightDesc = &pLocalLights[nLightCount];
+ if (!WorldLightToMaterialLight( state.locallight[i], *pLightDesc ))
+ continue;
+
+ // Apply lightstyle
+ float bias = LightStyleValue( state.locallight[i]->style );
+
+ // Deal with overbrighting + bias
+ pLightDesc->m_Color[0] *= bias;
+ pLightDesc->m_Color[1] *= bias;
+ pLightDesc->m_Color[2] *= bias;
+
+ if ( ++nLightCount >= nMaxLocalLights )
+ break;
+ }
+ return nLightCount;
+}
+
+void CEngineTool::GetServerFactory( CreateInterfaceFn& factory )
+{
+ factory = Sys_GetFactory( g_GameDLL );
+}
+
+void CEngineTool::GetClientFactory( CreateInterfaceFn& factory )
+{
+ factory = ClientDLL_GetFactory();
+}
+
+void CEngineTool::Command( const char *cmd )
+{
+ Cbuf_AddText( cmd );
+}
+
+void CEngineTool::Execute()
+{
+ Cbuf_Execute();
+}
+
+const char *CEngineTool::GetCurrentMap()
+{
+ if ( sv.IsDedicated() )
+ return "Dedicated Server";
+
+ if ( !cl.IsConnected() )
+ {
+ if ( sv.IsLoading() )
+ return sv.GetMapName();
+
+ return "";
+ }
+
+ return cl.m_szLevelFileName;
+}
+
+void CEngineTool::ChangeToMap( const char *mapname )
+{
+ if ( modelloader->Map_IsValid( mapname ) )
+ {
+ Cbuf_AddText( va( "map \"%s\"\n", mapname ) );
+ }
+}
+
+bool CEngineTool::IsMapValid( const char *mapname )
+{
+ return modelloader->Map_IsValid( mapname );
+}
+
+// Allows tools to kick off rendering by having the engine call the client
+void CEngineTool::RenderView( CViewSetup &view, int nFlags, int whatToRender )
+{
+ // Call client
+ g_ClientDLL->RenderView( view, nFlags, whatToRender );
+}
+
+void CEngineTool::SetIsInGame( bool bIsInGame )
+{
+ m_bIsInGame = bIsInGame;
+}
+
+bool CEngineTool::IsInGame()
+{
+ return m_bIsInGame && cl.IsConnected();
+}
+
+bool CEngineTool::IsConnected()
+{
+ return cl.IsConnected();
+}
+
+int CEngineTool::GetMaxClients()
+{
+ return cl.m_nMaxClients;
+}
+
+bool CEngineTool::IsGamePaused()
+{
+ return cl.IsPaused();
+}
+
+bool CEngineTool::IsConsoleVisible()
+{
+#ifdef SWDS
+ return false;
+#else
+ return EngineVGui()->IsConsoleVisible();
+#endif
+}
+
+void CEngineTool::SetGamePaused( bool paused )
+{
+ sv.SetPaused( paused );
+}
+
+float CEngineTool::GetTimescale()
+{
+ return host_timescale.GetFloat();
+}
+
+void CEngineTool::SetTimescale( float scale )
+{
+ host_timescale.SetValue( scale );
+}
+
+float CEngineTool::Time()
+{
+ return Plat_FloatTime();
+}
+
+// Real time is unscaled, but is updated once per frame
+float CEngineTool::GetRealTime()
+{
+ return realtime;
+}
+
+float CEngineTool::GetRealFrameTime()
+{
+ return host_frametime;
+}
+
+float CEngineTool::HostFrameTime()
+{
+ return host_frametime;
+}
+
+float CEngineTool::HostTime()
+{
+ return host_time;
+}
+
+int CEngineTool::HostTick()
+{
+ return host_tickcount;
+}
+
+int CEngineTool::HostFrameCount()
+{
+ return host_framecount;
+}
+
+float CEngineTool::ServerTime()
+{
+ return g_ServerGlobalVariables.curtime;
+}
+
+float CEngineTool::ServerFrameTime()
+{
+ return g_ServerGlobalVariables.frametime;
+}
+int CEngineTool::ServerTick()
+{
+ return g_ServerGlobalVariables.tickcount;
+}
+
+float CEngineTool::ServerTickInterval()
+{
+ return g_ServerGlobalVariables.interval_per_tick;
+}
+
+float CEngineTool::ClientTime()
+{
+ return g_ClientGlobalVariables.curtime;
+}
+
+float CEngineTool::ClientFrameTime()
+{
+ return g_ClientGlobalVariables.frametime;
+}
+
+int CEngineTool::ClientTick()
+{
+ return g_ClientGlobalVariables.tickcount;
+}
+
+void CEngineTool::SetClientFrameTime( float frametime )
+{
+ g_ClientGlobalVariables.frametime = frametime;
+}
+
+void CEngineTool::ForceUpdateDuringPause()
+{
+ SV_ForceSend();
+}
+
+model_t *CEngineTool::GetModel( HTOOLHANDLE hEntity )
+{
+ Assert( 0 );
+ return NULL;
+}
+
+studiohdr_t *CEngineTool::GetStudioModel( HTOOLHANDLE hEntity )
+{
+ Assert( 0 );
+ return NULL;
+}
+
+void CEngineTool::Con_NPrintf( int pos, const char *fmt, ... )
+{
+ char buf[ 1024 ];
+ va_list argptr;
+ va_start( argptr, fmt );
+ _vsnprintf( buf, sizeof( buf ) - 1, fmt, argptr );
+ va_end( argptr );
+
+ return ::Con_NPrintf( pos, "%s", buf );
+}
+
+void CEngineTool::Con_NXPrintf( const struct con_nprint_s *info, const char *fmt, ... )
+{
+ char buf[ 1024 ];
+ va_list argptr;
+ va_start( argptr, fmt );
+ _vsnprintf( buf, sizeof( buf ) - 1, fmt, argptr );
+ va_end( argptr );
+
+ ::Con_NXPrintf( info, "%s", buf );
+}
+
+void CEngineTool::GetGameDir( char *szGetGameDir, int maxlength )
+{
+ Q_strncpy( szGetGameDir, com_gamedir, maxlength );
+}
+
+void CEngineTool::GetScreenSize( int& width, int &height )
+{
+ CMatRenderContextPtr pRenderContext( materials );
+
+ pRenderContext->GetWindowSize( width, height );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Helpers for implementing a tool switching UI
+// Input : -
+// Output : int
+//-----------------------------------------------------------------------------
+int CEngineTool::GetToolCount() const
+{
+ return toolframework->GetToolCount();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+// Output : char
+//-----------------------------------------------------------------------------
+const char *CEngineTool::GetToolName( int index ) const
+{
+ return toolframework->GetToolName( index );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : index -
+//-----------------------------------------------------------------------------
+void CEngineTool::SwitchToTool( int index )
+{
+ toolframework->SwitchToTool( index );
+}
+
+bool CEngineTool::IsTopmostTool( const IToolSystem *sys ) const
+{
+ return toolframework->IsTopmostTool( sys );
+}
+
+IToolSystem *CEngineTool::GetTopmostTool()
+{
+ return toolframework->GetTopmostTool();
+}
+
+const IToolSystem *CEngineTool::GetToolSystem( int index ) const
+{
+ return toolframework->GetToolSystem( index );
+}
+
+int CEngineTool::StartSound(
+ int iUserData,
+ bool staticsound,
+ int iEntIndex,
+ int iChannel,
+ const char *pSample,
+ float flVolume,
+ soundlevel_t iSoundlevel,
+ const Vector& origin,
+ const Vector& direction,
+ int iFlags /*= 0*/,
+ int iPitch /*= PITCH_NORM*/,
+ bool bUpdatePositions /*= true*/,
+ float delay /*= 0.0f*/,
+ int speakerentity /*= -1*/ )
+{
+ StartSoundParams_t params;
+ params.userdata = iUserData;
+ params.staticsound = staticsound;
+ params.soundsource = iEntIndex;
+ params.entchannel = iChannel;
+ params.pSfx = S_PrecacheSound( pSample );
+ params.origin = origin;
+ params.direction = direction;
+ params.bUpdatePositions = bUpdatePositions;
+ params.fvol = flVolume;
+ params.soundlevel = iSoundlevel;
+ params.flags = iFlags;
+ params.pitch = iPitch;
+ params.fromserver = false;
+ params.delay = delay;
+ params.speakerentity = speakerentity;
+ params.suppressrecording = true;
+
+ int guid = S_StartSound( params );
+
+ return guid;
+}
+
+void CEngineTool::StopSoundByGuid( int guid )
+{
+ S_StopSoundByGuid( guid );
+}
+
+bool CEngineTool::IsSoundStillPlaying( int guid )
+{
+ return S_IsSoundStillPlaying( guid );
+}
+
+float CEngineTool::GetSoundDuration( int guid )
+{
+ return S_SoundDurationByGuid( guid );
+}
+
+float CEngineTool::GetSoundDuration( const char *pszName )
+{
+ return AudioSource_GetSoundDuration( pszName );
+}
+
+void CEngineTool::ReloadSound( const char *pSample )
+{
+ S_ReloadSound( pSample );
+}
+
+void CEngineTool::StopAllSounds( )
+{
+ S_StopAllSounds( true );
+}
+
+// Returns if the sound is looping
+bool CEngineTool::IsLoopingSound( int guid )
+{
+ return S_IsLoopingSoundByGuid( guid );
+}
+
+void CEngineTool::TraceRay( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace )
+{
+ trace_t tempTrace;
+
+ g_pEngineTraceClient->TraceRay( ray, fMask, pTraceFilter, &tempTrace );
+
+ memcpy( pTrace, &tempTrace, sizeof ( CBaseTrace ) );
+}
+
+
+void CEngineTool::TraceRayServer( const Ray_t &ray, unsigned int fMask, ITraceFilter *pTraceFilter, CBaseTrace *pTrace )
+{
+ trace_t tempTrace;
+
+ g_pEngineTraceServer->TraceRay( ray, fMask, pTraceFilter, &tempTrace );
+
+ memcpy( pTrace, &tempTrace, sizeof ( CBaseTrace ) );
+}
+
+
+void CEngineTool::SetAudioState( const AudioState_t &audioState )
+{
+ Host_SetAudioState( audioState );
+}
+
+
+// Sets the location of the main view
+void CEngineTool::SetMainView( const Vector &vecOrigin, const QAngle &angles )
+{
+ g_EngineRenderer->SetMainView( vecOrigin, angles );
+}
+
+static float ScaleFOVByWidthRatio( float fovDegrees, float ratio )
+{
+ float halfAngleRadians = fovDegrees * ( 0.5f * M_PI / 180.0f );
+ float t = tan( halfAngleRadians );
+ t *= ratio;
+ float retDegrees = ( 180.0f / M_PI ) * atan( t );
+ return retDegrees * 2.0f;
+}
+
+// Gets the player view
+bool CEngineTool::GetPlayerView( CViewSetup &viewSetup, int x, int y, int w, int h )
+{
+ if ( g_ClientDLL )
+ {
+ if ( !g_ClientDLL->GetPlayerView( viewSetup ) )
+ return false;
+
+ // Initialize view setup given the desired rectangle
+ viewSetup.x = x;
+ viewSetup.y = y;
+ viewSetup.width = w;
+ viewSetup.height = h;
+ viewSetup.m_flAspectRatio = (viewSetup.height != 0) ? (float)viewSetup.width / (float)viewSetup.height : 4.0f / 3.0f;
+ viewSetup.m_bRenderToSubrectOfLargerScreen = true;
+ viewSetup.fov = ScaleFOVByWidthRatio( viewSetup.fov, viewSetup.m_flAspectRatio / ( 4.0f / 3.0f ) );
+ viewSetup.fovViewmodel = ScaleFOVByWidthRatio( viewSetup.fovViewmodel, viewSetup.m_flAspectRatio / ( 4.0f / 3.0f ) );
+ return true;
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// From a location on the screen, figure out the vector into the world
+//-----------------------------------------------------------------------------
+
+void CEngineTool::CreatePickingRay( const CViewSetup &viewSetup, int x, int y, Vector& org, Vector& forward )
+{
+ // Remap x and y into -1 to 1 normalized space
+ float xf, yf;
+ xf = ( 2.0f * (float)x / (float)viewSetup.width ) - 1.0f;
+ yf = ( 2.0f * (float)y / (float)viewSetup.height ) - 1.0f;
+
+ // Flip y axis
+ yf = -yf;
+
+ VMatrix worldToScreen;
+ GetWorldToScreenMatrixForView( viewSetup, &worldToScreen );
+ VMatrix screenToWorld;
+ MatrixInverseGeneral( worldToScreen, screenToWorld );
+
+ // Create two points at the normalized mouse x, y pos and at the near and far z planes (0 and 1 depth)
+ Vector v1, v2;
+ v1.Init( xf, yf, 0.0f );
+ v2.Init( xf, yf, 1.0f );
+
+ Vector o2;
+ // Transform the two points by the screen to world matrix
+ screenToWorld.V3Mul( v1, org ); // ray start origin
+ screenToWorld.V3Mul( v2, o2 ); // ray end origin
+ VectorSubtract( o2, org, forward );
+ forward.NormalizeInPlace();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Returns true if all handlers say we can quit the engine
+//-----------------------------------------------------------------------------
+bool CEngineTool::CanQuit()
+{
+ int c = m_QuitHandlers.Count();
+ for ( int i = 0; i < c; ++i )
+ {
+ QuitHandler_t& qh = m_QuitHandlers[ i ];
+ FnQuitHandler func = qh.func;
+ if ( func )
+ {
+ if ( !func( qh.userdata ) )
+ {
+ return false;
+ }
+ }
+ }
+
+ return true;
+}
+
+void CEngineTool::InstallQuitHandler( void *pvUserData, FnQuitHandler func )
+{
+ QuitHandler_t qh;
+ qh.userdata = pvUserData;
+ qh.func = func;
+
+ m_QuitHandlers.AddToTail( qh );
+}
+
+// precache methods
+bool CEngineTool::PrecacheSound( const char *pName, bool bPreload )
+{
+ tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s(%s, %s)", __FUNCTION__, tmDynamicString( TELEMETRY_LEVEL0, pName ), bPreload ? "true" : "false" );
+
+ if ( pName && TestSoundChar( pName, CHAR_SENTENCE ) )
+ return true;
+
+ bool bState = networkStringTableContainerServer->Lock( false );
+ int flags = bPreload ? RES_PRELOAD : 0;
+ int i = sv.PrecacheSound( pName, flags );
+ networkStringTableContainerServer->Lock( bState );
+ return i >= 0;
+}
+
+bool CEngineTool::PrecacheModel( const char *pName, bool bPreload )
+{
+ int flags = bPreload ? RES_PRELOAD : 0;
+ bool bState = networkStringTableContainerServer->Lock( false );
+ int i = sv.PrecacheModel( pName, flags );
+ networkStringTableContainerServer->Lock( bState );
+ return i >= 0;
+}
+
+void CEngineTool::TakeTGAScreenShot( const char *filename, int width, int height )
+{
+ Q_strncpy( m_szScreenshotFile, filename, sizeof( m_szScreenshotFile ) );
+
+ m_nScreenshotWidth = width;
+ m_nScreenshotHeight = height;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CEngineTool::UpdateScreenshot()
+{
+ if ( g_LostVideoMemory )
+ return;
+
+ if ( m_szScreenshotFile[0] )
+ {
+ g_ClientDLL->WriteSaveGameScreenshotOfSize( m_szScreenshotFile, m_nScreenshotWidth, m_nScreenshotHeight );
+ m_szScreenshotFile[0] = 0;
+ }
+}
+
+// Even if game is paused, force networking to update to get new server state down to client
+void CEngineTool::ForceSend()
+{
+ SV_ForceSend();
+}
+
+bool CEngineTool::IsRecordingMovie()
+{
+ if ( m_bRecordingMovie )
+ {
+ Assert( CL_IsRecordingMovie() );
+ return true;
+ }
+ return false;
+}
+
+// NOTE: Params can contain file name, frame rate, output avi, output raw, and duration
+void CEngineTool::StartMovieRecording( KeyValues *pMovieParams )
+{
+ if ( CL_IsRecordingMovie() )
+ {
+ Warning( "Can't record movie, already recording!!!\n" );
+ return;
+ }
+
+ if ( m_bRecordingMovie )
+ return;
+
+ int jpeg_quality = DEFAULT_JPEG_QUALITY;
+
+ int flags = 0;
+ VideoSystem_t videoSystem = VideoSystem::NONE;
+ if ( pMovieParams->GetInt( "outputavi", 0 ) )
+ {
+ Warning( "Got a request to record a movie using AVI, but AVI is deprecated. Using QuickTime/H264 instead.\n" );
+ videoSystem = VideoSystem::QUICKTIME;
+ if ( pMovieParams->GetInt( "avisoundonly", 0 ) )
+ {
+ flags |= MovieInfo_t::FMOVIE_VIDSOUND;
+ }
+ else
+ {
+ flags |= MovieInfo_t::FMOVIE_VID | MovieInfo_t::FMOVIE_VIDSOUND;
+ }
+ }
+ if ( pMovieParams->GetInt( "outputtga", 0 ) )
+ {
+ flags |= MovieInfo_t::FMOVIE_TGA;
+ }
+ if ( pMovieParams->GetInt( "outputjpg", 0 ) )
+ {
+ flags |= MovieInfo_t::FMOVIE_JPG;
+ jpeg_quality = pMovieParams->GetInt( "jpeg_quality" );
+ }
+ if ( pMovieParams->GetInt( "outputwav", 0 ) )
+ {
+ flags |= MovieInfo_t::FMOVIE_WAV;
+ }
+
+ const char *pFileName = pMovieParams->GetString( "filename", NULL );
+ if ( !pFileName )
+ {
+ Warning( "Output filename not specified!\n" );
+ return;
+ }
+
+ int nWidth = pMovieParams->GetInt( "width", videomode->GetModeStereoWidth() );
+ int nHeight = pMovieParams->GetInt( "height", videomode->GetModeStereoHeight() );
+ float flFrameRate = pMovieParams->GetFloat( "framerate", 30.0f );
+
+ m_bRecordingMovie = true;
+ CL_StartMovie( pFileName, flags, nWidth, nHeight, flFrameRate, jpeg_quality, videoSystem );
+}
+
+void CEngineTool::EndMovieRecording()
+{
+ if ( !m_bRecordingMovie )
+ return;
+
+ CL_EndMovie();
+ m_bRecordingMovie = false;
+}
+
+void CEngineTool::CancelMovieRecording()
+{
+ EndMovieRecording();
+}
+
+
+IVideoRecorder *CEngineTool::GetActiveVideoRecorder()
+{
+ if ( !CL_IsRecordingMovie() )
+ {
+ return NULL;
+ }
+
+ return g_pVideoRecorder;
+}
+
+void Voice_ForceInit();
+
+bool CEngineTool::ShouldSuppressDeInit() const
+{
+ return m_bSuppressDeInit;
+}
+
+void CEngineTool::StartRecordingVoiceToFile( const char *filename, const char *pPathID /*= 0*/ )
+{
+ FileHandle_t fh = g_pFileSystem->Open( filename, "wb", pPathID );
+ if ( fh != FILESYSTEM_INVALID_HANDLE )
+ {
+ byte foo = 'b';
+
+ g_pFileSystem->Write( &foo, 1, fh );
+ g_pFileSystem->Close( fh );
+ }
+
+ g_pFileSystem->RelativePathToFullPath( filename, pPathID, m_szVoiceoverFile, sizeof( m_szVoiceoverFile ) );
+
+ g_pFileSystem->RemoveFile( filename, pPathID );
+
+#if !defined( NO_VOICE )
+ if ( IsVoiceRecording() )
+ {
+ Voice_RecordStop();
+ }
+ m_bSuppressDeInit = true;
+
+ Voice_ForceInit();
+ Voice_RecordStart( m_szVoiceoverFile, NULL, NULL);
+#endif
+}
+
+void CEngineTool::StopRecordingVoiceToFile()
+{
+#if !defined( NO_VOICE )
+ Voice_RecordStop();
+ m_bSuppressDeInit = false;
+#endif
+}
+
+float CEngineTool::GetMono16Samples( const char *pszName, CUtlVector< short >& sampleList )
+{
+ return S_GetMono16Samples( pszName, sampleList );
+}
+
+void CEngineTool::GetWorldToScreenMatrixForView( const CViewSetup &view, VMatrix *pVMatrix )
+{
+ VMatrix worldToView, viewToProjection;
+ ComputeViewMatrices( &worldToView, &viewToProjection, pVMatrix, view );
+}
+
+SpatialPartitionHandle_t CEngineTool::CreatePartitionHandle( IHandleEntity *pEntity,
+ SpatialPartitionListMask_t listMask, const Vector& mins, const Vector& maxs )
+{
+ return SpatialPartition()->CreateHandle( pEntity, listMask, mins, maxs );
+}
+
+void CEngineTool::DestroyPartitionHandle( SpatialPartitionHandle_t hPartition )
+{
+ SpatialPartition()->DestroyHandle( hPartition );
+}
+
+void CEngineTool::InstallPartitionQueryCallback( IPartitionQueryCallback *pQuery )
+{
+ SpatialPartition()->InstallQueryCallback( pQuery );
+}
+
+void CEngineTool::RemovePartitionQueryCallback( IPartitionQueryCallback *pQuery )
+{
+ SpatialPartition()->RemoveQueryCallback( pQuery );
+}
+
+void CEngineTool::ElementMoved( SpatialPartitionHandle_t handle, const Vector& mins, const Vector& maxs )
+{
+ SpatialPartition()->ElementMoved( handle, mins, maxs );
+}
+
+bool CEngineTool::IsVoiceRecording()
+{
+#if !defined( NO_VOICE )
+ return Voice_IsRecording();
+#else
+ return false;
+#endif
+}
+
+bool EngineTool_SuppressDeInit()
+{
+ return g_EngineTool.ShouldSuppressDeInit();
+}
+
+void EngineTool_OverrideSampleRate( int& rate )
+{
+ if ( EngineTool_SuppressDeInit() )
+ {
+ rate = 11025;
+ }
+}
+
+// Expose complex interface
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineTool, IEngineTool, VENGINETOOL_INTERFACE_VERSION, g_EngineTool );
+// Expose simple interface
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CEngineTool, IEngineToolFramework, VENGINETOOLFRAMEWORK_INTERFACE_VERSION, g_EngineTool );