305 lines
9.0 KiB
C++
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();
|
|
}
|