From 3bf9df6b2785fa6d951086978a3e66f49427166a Mon Sep 17 00:00:00 2001 From: FluorescentCIAAfricanAmerican <0934gj3049fk@protonmail.com> Date: Wed, 22 Apr 2020 12:56:21 -0400 Subject: 1 --- engine/enginetool.cpp | 1078 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1078 insertions(+) create mode 100644 engine/enginetool.cpp (limited to 'engine/enginetool.cpp') 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 ); -- cgit v1.2.3