csgo-2018-source/game/client/gameui.cpp
2021-07-24 21:11:47 -07:00

305 lines
9.0 KiB
C++

//===== Copyright (c) 1996-2009, Valve Corporation, All rights reserved. ====//
//
// Purpose: Contains all utility methods for the new game UI system
//
//===========================================================================//
#include "cbase.h"
#include "gameui.h"
#include "game_controls/igameuisystemmgr.h"
#include "tier1/timeutils.h"
#include "cdll_client_int.h"
#include "soundemittersystem/isoundemittersystembase.h"
#include "engine/ienginesound.h"
#include "filesystem.h"
#include "inputsystem/iinputstacksystem.h"
#include "gameui/basemodpanel.h"
#include "gameui/nuggets/ui_nugget.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// A logging channel used during engine initialization
DEFINE_LOGGING_CHANNEL_NO_TAGS( LOG_GameUI, "GameUI" );
LINK_GAME_CONTROLS_LIB();
// A utility function to determine if we are running as part of game ui base mod panel
inline bool IsPartOfGameUiBaseModPanel()
{
BaseModUI::CBaseModPanel *pPanel = BaseModUI::CBaseModPanel::GetSingletonPtr();
if ( !pPanel )
return false;
return pPanel->IsVisible();
}
//-----------------------------------------------------------------------------
// Default game ui sound playback implementation
//-----------------------------------------------------------------------------
class CInGameUISoundPlayback : public IGameUISoundPlayback
{
public:
void *EmitSound( const char *pSoundName )
{
if ( developer.GetBool() )
{
// Ensure the sound is valid
int nSoundIndex = g_pSoundEmitterSystem->GetSoundIndex( pSoundName );
if ( !g_pSoundEmitterSystem->IsValidIndex( nSoundIndex ) )
{
Log_Warning( LOG_GameUI, "Attempted to play invalid sound \"%s\"\n", pSoundName );
return NULL;
}
const char *pSourceFile = g_pSoundEmitterSystem->GetSourceFileForSound( nSoundIndex );
if ( !Q_stristr( pSourceFile, "game_sounds_ui.txt" ) )
{
Log_Warning( LOG_GameUI, "Attempted to play invalid sound \"%s\". This sound must be defined\n"
"in game_sounds_ui.txt but was defined in \"%s\" instead.\n", pSoundName, pSourceFile );
return NULL;
}
}
// Pull data from parameters
CSoundParameters params;
HSOUNDSCRIPTHASH handle = SOUNDEMITTER_INVALID_HASH;
if ( !soundemitterbase->GetParametersForSoundEx( pSoundName, handle, params, GENDER_NONE, true ) )
{
Log_Warning( LOG_GameUI, "Attempted to play invalid sound \"%s\"\n", pSoundName );
return NULL;
}
if ( !params.soundname[0] )
{
Log_Warning( LOG_GameUI, "Attempted to play invalid sound \"%s\", which has no .wav!\n", pSoundName );
return NULL;
}
float st = 0.0f;
if ( params.delay_msec != 0.0f )
{
st = gpGlobals->curtime + (float)params.delay_msec / 1000.f;
}
CLocalPlayerFilter filter;
enginesound->EmitSound(
filter,
SOUND_FROM_LOCAL_PLAYER,
params.channel,
pSoundName,
handle,
params.soundname,
params.volume,
(soundlevel_t)params.soundlevel,
params.m_nRandomSeed,
0, // flags
params.pitch,
NULL,
NULL,
NULL,
true,
st );
return (void*)enginesound->GetGuidForLastSoundEmitted();
}
void StopSound( void *pSoundHandle )
{
if ( !pSoundHandle || !g_pSoundSystem )
return;
int nGuid = (int)pSoundHandle;
enginesound->StopSoundByGuid( nGuid );
}
};
static CInGameUISoundPlayback s_InGameUISoundPlayback;
//-----------------------------------------------------------------------------
// Instantiate singleton game system
//-----------------------------------------------------------------------------
static CGameUIGameSystem s_GameUIGameSystem;
CGameUIGameSystem *g_pGameUIGameSystem = &s_GameUIGameSystem;
//-----------------------------------------------------------------------------
// Initialization
//-----------------------------------------------------------------------------
bool CGameUIGameSystem::Init()
{
g_pGameUISystemMgr->UseGameInputSystemEventQueue( true );
g_pGameUISystemMgr->SetSoundPlayback( &s_InGameUISoundPlayback );
g_pGameUISystemMgr->SetInputContext( engine->GetInputContext( ENGINE_INPUT_CONTEXT_GAMEUI ) );
// Register all client nugget factories
CUiNuggetFactoryRegistrarBase::RegisterAll();
return true;
}
void CGameUIGameSystem::Shutdown()
{
g_pGameUISystemMgr->SetSoundPlayback( NULL );
g_pGameUISystemMgr->SetInputContext( INPUT_CONTEXT_HANDLE_INVALID );
}
//-----------------------------------------------------------------------------
// PostInit
//-----------------------------------------------------------------------------
void CGameUIGameSystem::PostInit()
{
// This cannot happen in Init() because the audio system isn't set up
// at that point, and it needs to be for precache to succeed
PrecacheGameUISounds();
}
//-----------------------------------------------------------------------------
// Precaches all game UI sounds
//-----------------------------------------------------------------------------
void CGameUIGameSystem::PrecacheGameUISounds()
{
// Precache all UI sounds. These must exist in the game_sounds_ui.txt script file
KeyValues *pUIGameSounds = new KeyValues( "Game Instructor Counts" );
if ( !pUIGameSounds->LoadFromFile( g_pFullFileSystem, "scripts/game_sounds_ui.txt", "GAME" ) )
{
pUIGameSounds->deleteThis();
return;
}
for ( KeyValues *pKey = pUIGameSounds; pKey; pKey = pKey->GetNextKey() )
{
const char *pSoundName = pKey->GetName();
int nSoundIndex = soundemitterbase->GetSoundIndex( pSoundName );
if ( !soundemitterbase->IsValidIndex( nSoundIndex ) )
{
Log_Warning( LOG_GameUI, "GameUI: Unable to precache gamesound \"%s\"\n", pSoundName );
continue;
}
CSoundParametersInternal *pInternal = soundemitterbase->InternalGetParametersForSound( nSoundIndex );
if ( !pInternal )
{
Log_Warning( LOG_GameUI, "GameUI: Unable to precache gamesound \"%s\"\n", pSoundName );
continue;
}
int nWaveCount = pInternal->NumSoundNames();
if ( !nWaveCount )
{
Log_Warning( LOG_GameUI, "GameUI: game_sounds_ui.txt entry '%s' has no waves listed under 'wave' or 'rndwave' key!!!\n", pSoundName );
continue;
}
for( int nWave = 0; nWave < nWaveCount; ++nWave )
{
const char *pWavName = soundemitterbase->GetWaveName( pInternal->GetSoundNames()[ nWave ].symbol );
enginesound->PrecacheSound( pWavName, true, true );
}
}
pUIGameSounds->deleteThis();
}
//-----------------------------------------------------------------------------
// Reloads game GUI sounds
//-----------------------------------------------------------------------------
void CGameUIGameSystem::ReloadSounds()
{
// Should I stop all currently playing sounds?
PrecacheGameUISounds();
}
//-----------------------------------------------------------------------------
// Init any render targets needed by the UI.
//-----------------------------------------------------------------------------
void CGameUIGameSystem::InitRenderTargets()
{
g_pGameUISystemMgr->InitRenderTargets();
}
//-----------------------------------------------------------------------------
// Init any render targets needed by the UI.
//-----------------------------------------------------------------------------
IMaterialProxy *CGameUIGameSystem::CreateProxy( const char *proxyName )
{
return g_pGameUISystemMgr->CreateProxy( proxyName );
}
//-----------------------------------------------------------------------------
// Renders the game UI
//-----------------------------------------------------------------------------
void CGameUIGameSystem::Render( const Rect_t &viewport, float flCurrentTime )
{
g_pGameUISystemMgr->Render( viewport, DmeTime_t( flCurrentTime ) );
}
//-----------------------------------------------------------------------------
// Registers an input event
//-----------------------------------------------------------------------------
bool CGameUIGameSystem::RegisterInputEvent( const InputEvent_t &iEvent )
{
if ( !g_pGameUISystemMgr->GetGameUIVisible() )
return false;
switch( iEvent.m_nType )
{
case IE_ButtonPressed:
{
// NOTE: data2 is the virtual key code (data1 contains the scan-code one)
ButtonCode_t code = (ButtonCode_t)iEvent.m_nData2;
if ( code == KEY_BACKQUOTE )
{
return false;
}
else if ( code == KEY_ESCAPE )
{
return false;
}
}
break;
case IE_ButtonReleased:
{
// NOTE: data2 is the virtual key code (data1 contains the scan-code one)
ButtonCode_t code = (ButtonCode_t)iEvent.m_nData2;
if ( code == KEY_BACKQUOTE )
{
return false;
}
else if ( code == KEY_ESCAPE )
{
return false;
}
}
break;
default:
break;
}
g_pGameUISystemMgr->RegisterInputEvent( iEvent );
// FIXME: This is a hack; we're saying that the system eats the
// input as long as a menu is visible
return g_pGameUISystemMgr->GetGameUIVisible();
}
//-----------------------------------------------------------------------------
// Simulates the next frame
//-----------------------------------------------------------------------------
void CGameUIGameSystem::Update( float frametime )
{
if ( IsPartOfGameUiBaseModPanel() )
// Prevent double-updates during a frame when running as part of game ui
// base mod panel rendering and event processing
return;
g_pGameUISystemMgr->RunFrame();
}