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.
1566 lines
47 KiB
1566 lines
47 KiB
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
|
|
//
|
|
// Purpose:
|
|
//
|
|
// $NoKeywords: $
|
|
//===========================================================================//
|
|
|
|
#include "gameuisystemmgr.h"
|
|
#include "soundsystem/isoundsystem.h"
|
|
#include "SoundEmitterSystem/isoundemittersystembase.h"
|
|
#include "gameuisystem.h"
|
|
#include "tier2/fileutils.h"
|
|
#include "rendersystem/irenderdevice.h"
|
|
#include "rendersystem/irendercontext.h"
|
|
#include "inputgameui.h"
|
|
#include "gameuisystemsurface.h"
|
|
#include "inputsystem/iinputsystem.h"
|
|
#include "gamelayer.h"
|
|
#include "gameuiscriptsystem.h"
|
|
#include "inputsystem/iinputstacksystem.h"
|
|
#include "fmtstr.h"
|
|
#include "gametext.h"
|
|
|
|
#undef PlaySound
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
|
|
static CGameUIDynamicTextures *s_pDynamicTextures = NULL;
|
|
void OnRestore( int nChangeFlags )
|
|
{
|
|
if ( s_pDynamicTextures != NULL )
|
|
{
|
|
s_pDynamicTextures->OnRestore( nChangeFlags );
|
|
}
|
|
}
|
|
|
|
//
|
|
// MISC UTILS
|
|
//
|
|
|
|
class CGameUIMiscUtils : public IGameUIMiscUtils
|
|
{
|
|
public:
|
|
virtual bool PointTriangleHitTest( Vector2D tringleVert0, Vector2D tringleVert1, Vector2D tringleVert2, Vector2D point )
|
|
{
|
|
return ::PointTriangleHitTest( tringleVert0, tringleVert1, tringleVert2, point );
|
|
}
|
|
}
|
|
g_GameUIMiscUtils;
|
|
IGameUIMiscUtils *g_pGameUIMiscUtils = &g_GameUIMiscUtils;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Default game ui sound playback implementation
|
|
//-----------------------------------------------------------------------------
|
|
class CDefaultGameUISoundPlayback : public IGameUISoundPlayback
|
|
{
|
|
public:
|
|
void *EmitSound( const char *pSoundName )
|
|
{
|
|
if ( !g_pSoundSystem )
|
|
return NULL;
|
|
|
|
// Ensure the sound is valid
|
|
int nSoundIndex = g_pSoundEmitterSystem->GetSoundIndex( pSoundName );
|
|
if ( !g_pSoundEmitterSystem->IsValidIndex( nSoundIndex ) )
|
|
{
|
|
Warning( "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" ) )
|
|
{
|
|
Warning( "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 ( !g_pSoundEmitterSystem->GetParametersForSoundEx( pSoundName, handle, params, GENDER_NONE, true ) )
|
|
return NULL;
|
|
|
|
if ( !params.soundname[0] )
|
|
return NULL;
|
|
|
|
char pFileName[ MAX_PATH ];
|
|
Q_snprintf( pFileName, sizeof(pFileName), "sound/%s", params.soundname );
|
|
CAudioSource *pAudioSource = g_pSoundSystem->FindOrAddSound( pFileName );
|
|
if ( !pAudioSource )
|
|
return NULL;
|
|
|
|
// NOTE: We're currently ignoring the sound delay time from the parameters,
|
|
// as well as a bunch of other parameters. Oh well.
|
|
CAudioMixer *pMixer = NULL;
|
|
g_pSoundSystem->PlaySound( pAudioSource, params.volume, &pMixer );
|
|
return pAudioSource;
|
|
|
|
}
|
|
|
|
void StopSound( void *pSoundHandle )
|
|
{
|
|
if ( !pSoundHandle || !g_pSoundSystem )
|
|
return;
|
|
|
|
CAudioSource *pAudioSource = (CAudioSource*)pSoundHandle;
|
|
Assert( pAudioSource );
|
|
CAudioMixer *pMixer = g_pSoundSystem->FindMixer( pAudioSource );
|
|
g_pSoundSystem->StopSound( pMixer );
|
|
}
|
|
};
|
|
|
|
static CDefaultGameUISoundPlayback s_DefaultGameUISoundPlayback;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Default implementation of gameui system mgr
|
|
//-----------------------------------------------------------------------------
|
|
static CGameUISystemMgr s_GameUISystemMgr;
|
|
CGameUISystemMgr *g_pGameUISystemMgrImpl = &s_GameUISystemMgr;
|
|
|
|
void LinkGameControlsLib()
|
|
{
|
|
// This function is required for the linker to include CGameUISystemMgr
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Used to allow us to install the game ui system into the list of app systems
|
|
// that the client wants the engine to initialize
|
|
//-----------------------------------------------------------------------------
|
|
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CGameUISystemMgr, IGameUISystemMgr, GAMEUISYSTEMMGR_INTERFACE_VERSION, s_GameUISystemMgr );
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// shader programs
|
|
//-----------------------------------------------------------------------------
|
|
static const char s_pVertexShader[] =
|
|
"float4 v4OffsetScale : register( c0 ); "
|
|
"float4 v4InstanceCount : register( c255 ); "
|
|
"struct VS_INPUT "
|
|
"{ "
|
|
" float3 vPos : POSITION0; "
|
|
" float4 vColor : COLOR0; "
|
|
" float2 vTexCoord : TEXCOORD0; "
|
|
"}; "
|
|
" "
|
|
"struct VS_OUTPUT "
|
|
"{ "
|
|
" float4 vColor : COLOR0; "
|
|
" float2 vTexCoord : TEXCOORD0; "
|
|
" float4 projPos : POSITION0; "
|
|
"}; "
|
|
" "
|
|
"VS_OUTPUT main( const VS_INPUT v ) "
|
|
"{ "
|
|
" VS_OUTPUT o = ( VS_OUTPUT )0; "
|
|
" "
|
|
" o.projPos.xy = 2.0f * ( v.vPos.xy - v4OffsetScale.xy ) / ( v4OffsetScale.zw ) - float2( 1.0f, 1.0f );"
|
|
" o.projPos.y *= -1.0f; "
|
|
" o.projPos.z = 1; "
|
|
" o.projPos.w = 1; "
|
|
" o.vColor = v.vColor; "
|
|
" o.vTexCoord = v.vTexCoord; "
|
|
" return o; "
|
|
"} "
|
|
"";
|
|
|
|
static const char s_pPixelShader[] =
|
|
"struct PS_INPUT "
|
|
"{ "
|
|
" float4 vColor : COLOR0; "
|
|
" float2 vTexCoord : TEXCOORD0; "
|
|
"}; "
|
|
" "
|
|
"sampler BaseTextureSampler : register( s0 ); "
|
|
"float4 main( const PS_INPUT i ) : COLOR "
|
|
"{ "
|
|
" return i.vColor * tex2D( BaseTextureSampler, i.vTexCoord ); "
|
|
"} "
|
|
"";
|
|
|
|
static RenderInputLayoutField_t s_pGameUILayout[] =
|
|
{
|
|
DEFINE_PER_VERTEX_FIELD( 0, "position", 0, GameUIVertex_t, m_vecPosition )
|
|
DEFINE_PER_VERTEX_FIELD( 0, "color", 0, GameUIVertex_t, m_color )
|
|
DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 0, GameUIVertex_t, m_vecTexCoord )
|
|
};
|
|
|
|
|
|
|
|
IScriptManager *g_pScriptManager;
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Inherited from IAppSystem
|
|
//-----------------------------------------------------------------------------
|
|
bool CGameUISystemMgr::Connect( CreateInterfaceFn factory )
|
|
{
|
|
if ( !BaseClass::Connect( factory ) )
|
|
return false;
|
|
|
|
g_pScriptManager = (IScriptManager *)factory( VSCRIPT_INTERFACE_VERSION, NULL );
|
|
|
|
if ( !g_pScriptManager )
|
|
return false;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CGameUISystemMgr::Disconnect()
|
|
{
|
|
g_pScriptManager = NULL;
|
|
BaseClass::Disconnect();
|
|
}
|
|
|
|
void *CGameUISystemMgr::QueryInterface( const char *pInterfaceName )
|
|
{
|
|
if (!Q_strncmp( pInterfaceName, GAMEUISYSTEMMGR_INTERFACE_VERSION, Q_strlen( GAMEUISYSTEMMGR_INTERFACE_VERSION ) + 1))
|
|
return (IGameUISystemMgr*)this;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Less function for use with CUtlMap and CUtlString keys
|
|
//-----------------------------------------------------------------------------
|
|
bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs )
|
|
{
|
|
return ( Q_stricmp( lhs, rhs ) < 0 );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constructor
|
|
//-----------------------------------------------------------------------------
|
|
CGameUISystemMgr::CGameUISystemMgr() :
|
|
m_MenuSoundMap( UtlStringLessFunc ),
|
|
m_ScreenControllerMap( UtlStringLessFunc ),
|
|
m_GraphicClassMap( UtlStringLessFunc )
|
|
{
|
|
m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
|
|
m_hVertexShader = RENDER_SHADER_HANDLE_INVALID;
|
|
m_hPixelShader = RENDER_SHADER_HANDLE_INVALID;
|
|
m_hConstBuffer = CONSTANT_BUFFER_HANDLE_INVALID;
|
|
|
|
m_Viewport.x = 0;
|
|
m_Viewport.y = 0;
|
|
m_Viewport.width = 0;
|
|
m_Viewport.height = 0;
|
|
m_nWindowWidth = 0;
|
|
m_nWindowHeight = 0;
|
|
|
|
m_flCurrentTime = DmeTime_t(0);
|
|
m_Scheme = NULL;
|
|
|
|
m_RequestedKeyFocus = NULL;
|
|
|
|
m_bForceFocusUpdate = false;
|
|
m_bUseGameInputQueue = false;
|
|
|
|
m_hInputContext = INPUT_CONTEXT_HANDLE_INVALID;
|
|
|
|
m_pSoundPlayback = &s_DefaultGameUISoundPlayback;
|
|
|
|
m_bVisible = true;
|
|
|
|
m_bSetReleaseTimer = false;
|
|
m_ReleaseStartTime = DmeTime_t(0);
|
|
m_ReleaseTime = DmeTime_t(0);
|
|
|
|
if ( !g_pGameUISystemMgr )
|
|
g_pGameUISystemMgr = this;
|
|
|
|
m_pCursorText = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Destructor
|
|
//-----------------------------------------------------------------------------
|
|
CGameUISystemMgr::~CGameUISystemMgr()
|
|
{
|
|
if ( m_pCursorText )
|
|
{
|
|
delete m_pCursorText;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Initialize
|
|
//-----------------------------------------------------------------------------
|
|
static AppSystemInfo_t s_pDependencies[] =
|
|
{
|
|
{ "vstdlib.dll", EVENTSYSTEM_INTERFACE_VERSION },
|
|
{ "vscript.dll", VSCRIPT_INTERFACE_VERSION },
|
|
{ "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
|
|
{ "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
|
|
{ "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION },
|
|
{ NULL, NULL }
|
|
};
|
|
|
|
const AppSystemInfo_t* CGameUISystemMgr::GetDependencies()
|
|
{
|
|
return s_pDependencies;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Initialize
|
|
//-----------------------------------------------------------------------------
|
|
InitReturnVal_t CGameUISystemMgr::Init( )
|
|
{
|
|
m_bForceFocusUpdate = false;
|
|
m_bUseGameInputQueue = false;
|
|
m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
|
|
m_hInputContext = INPUT_CONTEXT_HANDLE_INVALID;
|
|
m_pSoundPlayback = &s_DefaultGameUISoundPlayback;
|
|
|
|
InitReturnVal_t nRetVal = BaseClass::Init();
|
|
if ( nRetVal != INIT_OK )
|
|
return nRetVal;
|
|
|
|
g_pInputGameUI->Init();
|
|
if ( g_pRenderDevice )
|
|
{
|
|
m_hInputLayout = g_pRenderDevice->CreateInputLayout( "GameUILayout", ARRAYSIZE( s_pGameUILayout ), s_pGameUILayout );
|
|
m_hVertexShader = g_pRenderDevice->CreateShader( RENDER_VERTEX_SHADER, s_pVertexShader, sizeof(s_pVertexShader), g_pRenderDevice->GetShaderVersionString(RENDER_VERTEX_SHADER) );
|
|
m_hPixelShader = g_pRenderDevice->CreateShader( RENDER_PIXEL_SHADER, s_pPixelShader, sizeof(s_pPixelShader), g_pRenderDevice->GetShaderVersionString(RENDER_PIXEL_SHADER) );
|
|
m_hConstBuffer = g_pRenderDevice->CreateConstantBuffer( 4 * sizeof( float ) );
|
|
Assert( m_hVertexShader != RENDER_SHADER_HANDLE_INVALID );
|
|
Assert( m_hPixelShader != RENDER_SHADER_HANDLE_INVALID );
|
|
}
|
|
|
|
g_pGameUISystemSurface->Init();
|
|
|
|
// Tell the input system to generate UI events
|
|
g_pInputSystem->AddUIEventListener();
|
|
|
|
m_Scheme = NULL;
|
|
SetViewportSize( 1024, 768 );
|
|
SetWindowSize( 1024, 768 );
|
|
|
|
m_bVisible = true;
|
|
m_RequestedKeyFocus = NULL;
|
|
|
|
m_flCurrentTime = DmeTime_t(0);
|
|
|
|
m_bSetReleaseTimer = false;
|
|
m_ReleaseTime = DmeTime_t(0);
|
|
|
|
|
|
s_pDynamicTextures = new CGameUIDynamicTextures;
|
|
|
|
// Load in a default scheme
|
|
if (!g_pGameUISchemeManager->LoadSchemeFromFile( "resource/BoxRocket.res", "GameUIDefaultScheme" ))
|
|
{
|
|
Assert( 0 );
|
|
}
|
|
|
|
// Dynamic textures not yet supported for source 2
|
|
if ( g_pMaterialSystem )
|
|
{
|
|
g_pMaterialSystem->AddRestoreFunc( OnRestore );
|
|
}
|
|
|
|
return INIT_OK;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Init any render targets needed by the UI.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::InitRenderTargets()
|
|
{
|
|
s_pDynamicTextures->InitRenderTargets();
|
|
}
|
|
|
|
IMaterialProxy *CGameUISystemMgr::CreateProxy( const char *proxyName )
|
|
{
|
|
if ( s_pDynamicTextures )
|
|
{
|
|
return s_pDynamicTextures->CreateProxy( proxyName );
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Shutdown
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::Shutdown()
|
|
{
|
|
if ( g_pMaterialSystem )
|
|
{
|
|
g_pMaterialSystem->RemoveRestoreFunc( OnRestore );
|
|
}
|
|
|
|
if ( s_pDynamicTextures )
|
|
{
|
|
delete s_pDynamicTextures;
|
|
}
|
|
|
|
if ( g_pRenderDevice )
|
|
{
|
|
g_pRenderDevice->DestroyConstantBuffer( m_hConstBuffer );
|
|
g_pRenderDevice->DestroyShader( RENDER_PIXEL_SHADER, m_hPixelShader );
|
|
g_pRenderDevice->DestroyShader( RENDER_VERTEX_SHADER, m_hVertexShader );
|
|
g_pRenderDevice->DestroyInputLayout( m_hInputLayout );
|
|
m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
|
|
}
|
|
|
|
// release all menus.
|
|
ReleaseAllGameUIScreens();
|
|
|
|
g_pGameUISystemSurface->Shutdown();
|
|
|
|
// Tell the input system we no longer need UI events
|
|
g_pInputSystem->RemoveUIEventListener();
|
|
|
|
BaseClass::Shutdown();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Set visibility of the entire gameui.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetGameUIVisible( bool bVisible )
|
|
{
|
|
m_bVisible = bVisible;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::UseGameInputSystemEventQueue( bool bEnable )
|
|
{
|
|
m_bUseGameInputQueue = bEnable;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::RegisterInputEvent( const InputEvent_t &iEvent )
|
|
{
|
|
Assert( m_bUseGameInputQueue );
|
|
m_InputQueue.AddToTail( iEvent );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SendEventToAllScreens( KeyValues *kvGlobalEvent )
|
|
{
|
|
KeyValues::AutoDelete autodelete( kvGlobalEvent );
|
|
|
|
for ( int j = 0; j < m_ActiveMenuList.Count(); ++j )
|
|
{
|
|
if ( m_bVisible && m_ActiveMenuList[j]->Definition().GetVisible() )
|
|
{
|
|
m_ActiveMenuList[j]->ExecuteScript( kvGlobalEvent );
|
|
}
|
|
}
|
|
}
|
|
|
|
void CGameUISystemMgr::PostEventToAllScreens( KeyValues *kvGlobalEvent )
|
|
{
|
|
m_GameUIEventMainQueue.AddToTail( kvGlobalEvent );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Return true if any menu is visible.
|
|
//-----------------------------------------------------------------------------
|
|
bool CGameUISystemMgr::IsMenuVisible() const
|
|
{
|
|
if ( !m_bVisible )
|
|
return false;
|
|
|
|
int nCount = m_ActiveMenuList.Count();
|
|
for ( int i = 0; i < nCount; ++i )
|
|
{
|
|
if ( m_ActiveMenuList[i] )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().GetVisible() )
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Specifies the input context handle to use to allow it to interoperate
|
|
// with other input clients
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetInputContext( InputContextHandle_t hInputContext )
|
|
{
|
|
m_hInputContext = hInputContext;
|
|
|
|
if ( m_hInputContext != INPUT_CONTEXT_HANDLE_INVALID )
|
|
{
|
|
g_pInputStackSystem->EnableInputContext( m_hInputContext, IsMenuVisible() );
|
|
g_pInputStackSystem->SetCursorIcon( m_hInputContext, g_pInputSystem->GetStandardCursor( INPUT_CURSOR_ARROW ) );
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Returns the input context to use to control the cursor
|
|
//-----------------------------------------------------------------------------
|
|
InputContextHandle_t CGameUISystemMgr::GetInputContext( ) const
|
|
{
|
|
return m_hInputContext;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Allows you to control sound playback
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetSoundPlayback( IGameUISoundPlayback *pPlayback )
|
|
{
|
|
m_pSoundPlayback = pPlayback ? pPlayback : &s_DefaultGameUISoundPlayback;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Assign the scheme
|
|
// This is because the scheme is needed to load text ui elements
|
|
// so the def has to be able to assign it.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetScheme( IGameUIScheme * scheme )
|
|
{
|
|
if ( m_Scheme && m_Scheme != scheme )
|
|
{
|
|
Warning( "Warning game menus do not all share the same scheme, text might look strange or fail to display.\n" );
|
|
}
|
|
m_Scheme = scheme;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IGameUIScheme * CGameUISystemMgr::GetCurrentScheme()
|
|
{
|
|
// Currently the rendersystemtest text is being loaded with no scheme
|
|
return m_Scheme;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Load a game UI into memory.
|
|
// Return the menu id.
|
|
//-----------------------------------------------------------------------------
|
|
IGameUISystem * CGameUISystemMgr::LoadGameUIScreen( KeyValues *kvScreenLoadSettings )
|
|
{
|
|
if ( !kvScreenLoadSettings )
|
|
return NULL;
|
|
|
|
// Make a copy for safe modifications
|
|
kvScreenLoadSettings = kvScreenLoadSettings->MakeCopy();
|
|
KeyValues::AutoDelete autodelete_kvScreenLoadSettings( kvScreenLoadSettings );
|
|
|
|
char const *szName = kvScreenLoadSettings->GetName();
|
|
CFmtStr sFilename( "vguiedit/%s.gui", szName );
|
|
const char *pFilename = sFilename;
|
|
|
|
// Current menu
|
|
IGameUISystem *pPreviousScreen = NULL;
|
|
if ( m_ActiveMenuList.Count() )
|
|
{
|
|
pPreviousScreen = m_ActiveMenuList[ m_ActiveMenuList.Count() - 1 ];
|
|
}
|
|
|
|
// Always load a new instance of the menu
|
|
CGameUISystem *pNewScreen = NULL;
|
|
if ( !pNewScreen )
|
|
{
|
|
bool bSuccess = false;
|
|
if ( szName && *szName )
|
|
{
|
|
CUtlBuffer buf( 0, 0, IsPlatformX360() ? 0 : CUtlBuffer::TEXT_BUFFER );
|
|
if ( IsPlatformX360() )
|
|
{
|
|
buf.ActivateByteSwapping( true );
|
|
}
|
|
|
|
bSuccess = g_pFullFileSystem->ReadFile( pFilename, "GAME", buf );
|
|
if ( bSuccess )
|
|
{
|
|
CGameUISystem *pGameUI = new CGameUISystem;
|
|
bSuccess = pGameUI->LoadGameUIDefinition( buf, pFilename );
|
|
if ( bSuccess )
|
|
{
|
|
pNewScreen = pGameUI;
|
|
|
|
pGameUI->Init( kvScreenLoadSettings );
|
|
}
|
|
else
|
|
{
|
|
delete pGameUI;
|
|
Warning( "Failed to load game ui file %s\n", pFilename );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Warning( "Failed to read game ui file %s\n", pFilename );
|
|
}
|
|
}
|
|
|
|
// Failed to read or load file. Load an empty ui instead.
|
|
if ( !bSuccess )
|
|
{
|
|
CGameUISystem *pGameUI = new CGameUISystem;
|
|
// for the name use the menu name of the file we tried to load
|
|
char pFilenameStripped[ MAX_PATH ];
|
|
int len = Q_strlen( pFilename );
|
|
Q_StripExtension( pFilename, pFilenameStripped, len+1 );
|
|
|
|
CUtlVector<char *> words;
|
|
V_SplitString( pFilenameStripped, "/", words );
|
|
int lastWord = words.Count() - 1;
|
|
char *pMenuName = words[lastWord];
|
|
|
|
pGameUI->LoadEmptyGameUI( pMenuName );
|
|
pGameUI->Init( kvScreenLoadSettings );
|
|
|
|
IGameUIScheme *pNewUIScheme = pGameUI->Definition().GetScheme();
|
|
// Empty UI's should never stomp an already existing scheme.
|
|
if ( !m_Scheme )
|
|
{
|
|
m_Scheme = pNewUIScheme;
|
|
}
|
|
|
|
pNewScreen = pGameUI;
|
|
}
|
|
}
|
|
|
|
Assert( pNewScreen );
|
|
|
|
pNewScreen->Definition().InitializeScripts();
|
|
|
|
// Set it visible etc.
|
|
pNewScreen->Definition().SetVisible( true );
|
|
pNewScreen->Definition().SetAcceptInput( false );
|
|
|
|
kvScreenLoadSettings->SetName( "OnLoad" );
|
|
kvScreenLoadSettings->SetInt( "scripthandle", pNewScreen->GetScriptHandle() );
|
|
pNewScreen->ExecuteScript( kvScreenLoadSettings );
|
|
|
|
pNewScreen->Definition().SetAcceptInput( true );
|
|
|
|
// Stack operation:
|
|
char const *szDefaultStackOperation = "removeall";
|
|
char const *szStackOperation = kvScreenLoadSettings->GetString( "stack", szDefaultStackOperation );
|
|
if ( Q_stricmp( "append", szStackOperation ) != 0 )
|
|
{
|
|
// Take the old stack and move it into the m_ReleasedMenuList
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
m_ReleasedMenuList.AddToTail( m_ActiveMenuList[i] );
|
|
}
|
|
|
|
// Tell the previous stack to exit
|
|
KeyValues *kvEventOnExit = new KeyValues( "OnExit");
|
|
KeyValues::AutoDelete autodelete_kvEventOnExit( kvEventOnExit );
|
|
for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
|
|
{
|
|
m_ReleasedMenuList[i]->Definition().SetAcceptInput( false );
|
|
m_ReleasedMenuList[i]->ExecuteScript( kvEventOnExit );
|
|
|
|
// null out requested focus for a released panel
|
|
if ( m_RequestedKeyFocus && m_ReleasedMenuList[i]->Definition().HasGraphic( m_RequestedKeyFocus ) )
|
|
{
|
|
m_RequestedKeyFocus = NULL;
|
|
}
|
|
}
|
|
m_ReleaseTime = DmeTime_t(0);
|
|
m_bSetReleaseTimer = true;
|
|
|
|
m_ActiveMenuList.RemoveAll();
|
|
}
|
|
|
|
// Push the new screen onto the stack
|
|
m_ActiveMenuList.AddToTail( pNewScreen );
|
|
|
|
// Init the newly loaded menu
|
|
// ? not sure if we would want to merge load and init ?
|
|
// we may control execution of scripts with passed in keyvalues
|
|
kvScreenLoadSettings->SetName( "OnInit" );
|
|
pNewScreen->ExecuteScript( kvScreenLoadSettings );
|
|
|
|
|
|
return pNewScreen;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::ReleaseAllGameUIScreens()
|
|
{
|
|
while ( m_ActiveMenuList.Count() )
|
|
{
|
|
CGameUISystem *pTopScreen = m_ActiveMenuList.Tail();
|
|
m_ActiveMenuList.RemoveMultipleFromTail( 1 );
|
|
|
|
// need to release at safe point: pTopScreen->Release();
|
|
DevMsg( "CGameUISystemMgr scheduled screen %p for release\n", pTopScreen );
|
|
m_ReleasedMenuList.AddToTail( pTopScreen );
|
|
|
|
m_ReleaseTime = DmeTime_t(0);
|
|
m_bSetReleaseTimer = true;
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::OnScreenReleased( CGameUISystem *pScreen )
|
|
{
|
|
// Assuming that all the logic of transferring context/focus
|
|
// from the released screen already happened
|
|
if ( m_ActiveMenuList.FindAndRemove( pScreen ) )
|
|
{
|
|
DevWarning( "CGameUISystemMgr::OnScreenReleased( %p ) while screen is active!\n", pScreen );
|
|
}
|
|
|
|
// null out requested focus for a released panel
|
|
if ( m_RequestedKeyFocus && pScreen->Definition().HasGraphic( m_RequestedKeyFocus ) )
|
|
{
|
|
m_RequestedKeyFocus = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Process input.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::RunFrame()
|
|
{
|
|
// All released menus are removed after a few seconds to allow them to clean up.
|
|
if ( m_ReleaseTime > DmeTime_t( 5.0 ) && m_ReleasedMenuList.Count() )
|
|
{
|
|
for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
|
|
{
|
|
CGameUISystem *&pReleasedScreen = m_ReleasedMenuList[i];
|
|
pReleasedScreen->Release();
|
|
pReleasedScreen = NULL;
|
|
}
|
|
m_ReleasedMenuList.RemoveAll();
|
|
}
|
|
|
|
//
|
|
// MAIN UPDATE LOOP
|
|
//
|
|
{
|
|
// Regenerate if we should.
|
|
if ( s_pDynamicTextures )
|
|
{
|
|
s_pDynamicTextures->RegenerateTexture( 0 );
|
|
}
|
|
|
|
|
|
// Update keyfocused and reset mouse and key states.
|
|
g_pInputGameUI->RunFrame();
|
|
m_RequestedKeyFocus = NULL;
|
|
|
|
// Generate all gameui event messages
|
|
// Run scripts to handle them.
|
|
for ( int i = 0; i < m_GameUIEventMainQueue.Count(); ++i )
|
|
{
|
|
KeyValues *kvEvent = m_GameUIEventMainQueue[i];
|
|
KeyValues::AutoDelete autodelete( kvEvent );
|
|
|
|
for ( int j = 0; j < m_ActiveMenuList.Count(); ++j )
|
|
{
|
|
if ( m_bVisible && m_ActiveMenuList[j]->Definition().GetVisible() )
|
|
{
|
|
m_ActiveMenuList[j]->ExecuteScript( kvEvent );
|
|
}
|
|
}
|
|
}
|
|
m_GameUIEventMainQueue.RemoveAll();
|
|
|
|
// Generate all input messages
|
|
// this will generate all key and mouse events
|
|
|
|
const InputEvent_t* pEvents = NULL;
|
|
int nEventCount = 0;
|
|
if ( m_bUseGameInputQueue )
|
|
{
|
|
nEventCount = m_InputQueue.Count();
|
|
pEvents = m_InputQueue.Base();
|
|
}
|
|
else
|
|
{
|
|
nEventCount = g_pInputSystem->GetEventCount();
|
|
pEvents = g_pInputSystem->GetEventData();
|
|
}
|
|
|
|
for ( int i = 0; i < nEventCount; ++i )
|
|
{
|
|
InputGameUIHandleInputEvent( pEvents[i] );
|
|
}
|
|
|
|
m_InputQueue.RemoveAll();
|
|
|
|
// Specifically post the current mouse position as a message
|
|
g_pInputGameUI->PostCursorMessage();
|
|
if ( m_bForceFocusUpdate )
|
|
{
|
|
g_pInputGameUI->ForceInputFocusUpdate();
|
|
m_bForceFocusUpdate = false;
|
|
}
|
|
|
|
g_pInputGameUI->ProcessEvents();
|
|
|
|
// Run scripts.
|
|
KeyValues *kvEventOnUpdate = new KeyValues( "OnUpdate" );
|
|
KeyValues::AutoDelete autodelete_kvEventOnUpdate( kvEventOnUpdate );
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().GetVisible() )
|
|
{
|
|
m_ActiveMenuList[i]->ExecuteScript( kvEventOnUpdate );
|
|
}
|
|
}
|
|
for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
|
|
{
|
|
if ( m_ReleasedMenuList[i]->Definition().GetVisible() )
|
|
{
|
|
m_ReleasedMenuList[i]->ExecuteScript( kvEventOnUpdate );
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
// FIXME: Need better logic here.
|
|
// Our input context is enabled if any menus are visible
|
|
if ( m_hInputContext != INPUT_CONTEXT_HANDLE_INVALID )
|
|
{
|
|
g_pInputStackSystem->EnableInputContext( m_hInputContext, IsMenuVisible() );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::RegisterScreenControllerFactory( char const *szControllerName, IGameUIScreenControllerFactory *pFactory )
|
|
{
|
|
m_ScreenControllerMap.InsertOrReplace( szControllerName, pFactory );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IGameUIScreenControllerFactory *CGameUISystemMgr::GetScreenControllerFactory( char const *szControllerName )
|
|
{
|
|
ScreenControllerFactoryMap::IndexType_t idx = m_ScreenControllerMap.Find( szControllerName );
|
|
if ( idx != m_ScreenControllerMap.InvalidIndex() )
|
|
return m_ScreenControllerMap[idx];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Registers a factory to create a graphic class type (rect, text, hitarea)
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::RegisterGraphicClassFactory( char const *szGraphicClassName, IGameUIGraphicClassFactory *pFactory )
|
|
{
|
|
m_GraphicClassMap.InsertOrReplace( szGraphicClassName, pFactory );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the factory to create an instance of a graphic class ( rect, text, hitarea)
|
|
//-----------------------------------------------------------------------------
|
|
IGameUIGraphicClassFactory *CGameUISystemMgr::GetGraphicClassFactory( char const *szGraphicClassName )
|
|
{
|
|
GameUIGraphicClassFactoryMap::IndexType_t idx = m_GraphicClassMap.Find( szGraphicClassName );
|
|
if ( idx != m_GraphicClassMap.InvalidIndex() )
|
|
return m_GraphicClassMap[idx];
|
|
else
|
|
return NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IGameUISystemSurface * CGameUISystemMgr::GetSurface()
|
|
{
|
|
return g_pGameUISystemSurface;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IGameUISchemeMgr * CGameUISystemMgr::GetSchemeMgr()
|
|
{
|
|
return g_pGameUISchemeManager;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
IGameUIMiscUtils * CGameUISystemMgr::GetMiscUtils()
|
|
{
|
|
return g_pGameUIMiscUtils;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// ConCommand to trigger the menu for testing purposes
|
|
//-----------------------------------------------------------------------------
|
|
CON_COMMAND_F( ui_setmenus_hidden, "Hide the game ui", FCVAR_DEVELOPMENTONLY )
|
|
{
|
|
g_pGameUISystemMgrImpl->SetGameUIVisible( false );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Sets the current game UI menu.
|
|
//-----------------------------------------------------------------------------
|
|
CON_COMMAND_F( ui_setmenu, "Pass in a name; load it as the current game menu.", FCVAR_DEVELOPMENTONLY )
|
|
{
|
|
if ( args.ArgC() != 2 )
|
|
{
|
|
Msg( "ui_setmenu <name>\n" );
|
|
return;
|
|
}
|
|
|
|
const char *szName = args[ 1 ];
|
|
g_pGameUISystemMgrImpl->LoadGameUIScreen( KeyValues::AutoDeleteInline( new KeyValues( szName ) ) );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Source 1
|
|
// Draw each gameui, note game uis render from back to front.
|
|
// A newly loaded gameui goes in the front.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::Render( const Rect_t &viewport, DmeTime_t flCurrentTime )
|
|
{
|
|
if ( m_bSetReleaseTimer )
|
|
{
|
|
m_ReleaseStartTime = flCurrentTime;
|
|
m_bSetReleaseTimer = false;
|
|
}
|
|
else
|
|
{
|
|
m_ReleaseTime = flCurrentTime - m_ReleaseStartTime;
|
|
}
|
|
m_flCurrentTime = flCurrentTime;
|
|
|
|
if ( !m_bVisible )
|
|
return;
|
|
|
|
|
|
|
|
// Check if the viewport size has changed.
|
|
if ( ( m_Viewport.width != viewport.width ) ||
|
|
( m_Viewport.height != viewport.height ) )
|
|
{
|
|
m_Viewport.width = viewport.width;
|
|
m_Viewport.height = viewport.height;
|
|
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
|
int nWidth, nHeight;
|
|
pRenderContext->GetWindowSize( nWidth, nHeight );
|
|
SetWindowSize( nWidth, nHeight );
|
|
|
|
// Update stage render transforms so the font size loaded is correct.
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
m_ActiveMenuList[i]->Definition().UpdateAspectRatio( viewport );
|
|
}
|
|
|
|
// Reload the fonts!
|
|
g_pGameUISystemSurface->ResetFontCaches();
|
|
}
|
|
|
|
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
m_ActiveMenuList[i]->Render( viewport );
|
|
}
|
|
|
|
// Render menus that are going away last (so they are in front)
|
|
for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
|
|
{
|
|
m_ReleasedMenuList[i]->Render( viewport );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Source 2
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::Render( IRenderContext *pRenderContext, PlatWindow_t hWnd, const Rect_t &viewport, DmeTime_t flCurrentTime )
|
|
{
|
|
// Check if the viewport size has changed.
|
|
if ( ( m_Viewport.width != viewport.width ) ||
|
|
( m_Viewport.height != viewport.height ) )
|
|
{
|
|
// Reload the fonts!
|
|
m_Viewport.width = viewport.width;
|
|
m_Viewport.height = viewport.height;
|
|
|
|
int nWidth, nHeight;
|
|
Plat_GetWindowClientSize( hWnd, &nWidth, &nHeight );
|
|
SetWindowSize( nWidth, nHeight );
|
|
|
|
// Update stage render transforms so the font size loaded is correct.
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
m_ActiveMenuList[i]->Definition().UpdateAspectRatio( viewport );
|
|
}
|
|
|
|
g_pGameUISystemSurface->ResetFontCaches();
|
|
}
|
|
|
|
m_flCurrentTime = flCurrentTime;
|
|
|
|
for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
|
|
{
|
|
m_ActiveMenuList[i]->Render( pRenderContext, viewport );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the current graphic that can accept mouse input and is under the mouse.
|
|
//-----------------------------------------------------------------------------
|
|
CHitArea *CGameUISystemMgr::GetMouseFocus()
|
|
{
|
|
return g_pInputGameUI->GetMouseFocus();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the graphic that can accept mouse input and is under the mouse.
|
|
// We check from front to back.
|
|
//-----------------------------------------------------------------------------
|
|
CHitArea *CGameUISystemMgr::GetMouseFocus( int x, int y )
|
|
{
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >=0; --i )
|
|
{
|
|
CHitArea *pGraphic = m_ActiveMenuList[i]->Definition().GetMouseFocus( x, y );
|
|
if ( pGraphic )
|
|
{
|
|
return pGraphic;
|
|
}
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the graphic that can accept key input
|
|
//-----------------------------------------------------------------------------
|
|
CHitArea *CGameUISystemMgr::GetKeyFocus()
|
|
{
|
|
return g_pInputGameUI->GetKeyFocus();
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Get the graphic that would like to accept key input
|
|
//-----------------------------------------------------------------------------
|
|
CHitArea *CGameUISystemMgr::GetRequestedKeyFocus()
|
|
{
|
|
return m_RequestedKeyFocus;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Request key focus. If focus is changed play a sound.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::RequestKeyFocus( CHitArea *pGraphic, KeyValues *args )
|
|
{
|
|
// Find the menu this graphic is in
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >=0; --i )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().GetVisible() )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().HasGraphic( pGraphic ) )
|
|
{
|
|
if ( !m_ActiveMenuList[i]->Definition().CanAcceptInput() )
|
|
{
|
|
Warning( "Key Focus requested for graphic %d that does not have input on in its menu!", pGraphic->GetName() );
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// Has nobody asked for it?
|
|
if ( m_RequestedKeyFocus == NULL )
|
|
{
|
|
if ( pGraphic->IsGroup() )
|
|
{
|
|
// Find a hitarea inside.
|
|
CGraphicGroup *pGroup = (CGraphicGroup *)pGraphic;
|
|
CHitArea *pFocusGraphic = pGroup->GetKeyFocusRequestGraphic();
|
|
if ( pFocusGraphic )
|
|
{
|
|
m_RequestedKeyFocus = pFocusGraphic;
|
|
PlayMenuSound( args->GetString( "sound" ) );
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
m_RequestedKeyFocus = pGraphic;
|
|
PlayMenuSound( args->GetString( "sound" ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: Obtain the screen size.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::GetScreenSize( int &nWide, int &nTall )
|
|
{
|
|
if ( !g_pMaterialSystem )
|
|
{
|
|
nWide = m_Viewport.width;
|
|
nTall = m_Viewport.height;
|
|
}
|
|
else
|
|
{
|
|
Rect_t viewport;
|
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
|
pRenderContext->GetViewport( viewport.x, viewport.y, nWide, nTall );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Assumes all menus are full screen and same size right now.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::GetScreenHeightForFontLoading( int &nTall )
|
|
{
|
|
Vector2D stageSize;
|
|
if ( m_ActiveMenuList.Count() )
|
|
{
|
|
m_ActiveMenuList[0]->Definition().GetMaintainAspectRatioStageSize( stageSize );
|
|
nTall = stageSize.y;
|
|
}
|
|
else
|
|
{
|
|
int nWide;
|
|
GetScreenSize( nWide, nTall );
|
|
}
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
DmeTime_t CGameUISystemMgr::GetTime()
|
|
{
|
|
return m_flCurrentTime;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: If the hit graphic'c menu is set to have mouse focus change keyboard focus, update kb focus.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::OnMouseFocusGained( CHitArea *mouseFocus )
|
|
{
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().GetVisible() &&
|
|
m_ActiveMenuList[i]->Definition().HasGraphic( mouseFocus ) )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().IsMouseFocusEqualToKeyboardFocus() )
|
|
{
|
|
m_RequestedKeyFocus = mouseFocus;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Purpose: If the hit graphic'c menu is set to have mouse focus change keyboard focus, update kb focus.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::OnMouseFocusLost( CHitArea *mouseFocus )
|
|
{
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().GetVisible() &&
|
|
m_ActiveMenuList[i]->Definition().HasGraphic( mouseFocus ) )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().IsMouseFocusEqualToKeyboardFocus() )
|
|
{
|
|
m_RequestedKeyFocus = NULL;
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// This fxn was called because nothing in the ui has keyfocus and a key was typed.
|
|
//-----------------------------------------------------------------------------
|
|
bool CGameUISystemMgr::OnKeyCodeTyped( const ButtonCode_t &code )
|
|
{
|
|
if ( code == KEY_TAB )
|
|
{
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
|
|
{
|
|
CHitArea *pGraphic = m_ActiveMenuList[i]->Definition().GetNextFocus( g_pInputGameUI->GetKeyFocus() );
|
|
if ( pGraphic )
|
|
{
|
|
RequestKeyFocus( pGraphic );
|
|
//pGraphic->OnGainKeyFocus(); // hack to make on focus anims and script events play
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
bool CGameUISystemMgr::OnGameGraphicScriptEvent( CGameGraphic *pGraphic, KeyValues *kvEvent )
|
|
{
|
|
// Find the menu that owns this graphic
|
|
for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
|
|
{
|
|
if ( m_ActiveMenuList[i]->Definition().HasGraphic( pGraphic ) )
|
|
{
|
|
CUtlString sGraphicName;
|
|
m_ActiveMenuList[i]->Definition().BuildScopedGraphicName( sGraphicName, pGraphic );
|
|
kvEvent->SetString( "graphic", sGraphicName.Get() );
|
|
return m_ActiveMenuList[i]->ExecuteScript( kvEvent );
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// This fxn was called because nothing in the ui has keyfocus and a key code was typed.
|
|
//-----------------------------------------------------------------------------
|
|
bool CGameUISystemMgr::OnKeyTyped( const wchar_t &unichar )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::PlayMenuSound( const char *pSoundName )
|
|
{
|
|
if ( pSoundName == NULL || pSoundName[ 0 ] == '\0' )
|
|
return;
|
|
|
|
int index = m_MenuSoundMap.Find( pSoundName );
|
|
if ( index != m_MenuSoundMap.InvalidIndex() )
|
|
{
|
|
m_pSoundPlayback->StopSound( m_MenuSoundMap[index] );
|
|
}
|
|
else
|
|
{
|
|
index = m_MenuSoundMap.Insert( pSoundName, NULL );
|
|
}
|
|
|
|
m_MenuSoundMap[index] = m_pSoundPlayback->EmitSound( pSoundName );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::StopMenuSound( const char *pSoundName )
|
|
{
|
|
int index = m_MenuSoundMap.Find( pSoundName );
|
|
if ( index == m_MenuSoundMap.InvalidIndex() )
|
|
return;
|
|
|
|
if ( m_MenuSoundMap[index] )
|
|
{
|
|
m_pSoundPlayback->StopSound( m_MenuSoundMap[index] );
|
|
m_MenuSoundMap[index] = NULL;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetWindowSize( int nWidth, int nHeight )
|
|
{
|
|
m_nWindowWidth = nWidth;
|
|
m_nWindowHeight = nHeight;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::GetWindowSize( int &nWidth, int &nHeight )
|
|
{
|
|
nWidth = m_nWindowWidth;
|
|
nHeight = m_nWindowHeight;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::SetViewportSize( int nWidth, int nHeight )
|
|
{
|
|
m_Viewport.width = nWidth;
|
|
m_Viewport.height = nHeight;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::GetViewportSize( int &nWidth, int &nHeight )
|
|
{
|
|
nWidth = m_Viewport.width;
|
|
nHeight = m_Viewport.height;
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Create an entry for this alias
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::InitImageAlias( const char *pAlias )
|
|
{
|
|
if ( s_pDynamicTextures == NULL )
|
|
{
|
|
s_pDynamicTextures = new CGameUIDynamicTextures;
|
|
}
|
|
|
|
if ( !pAlias || !*pAlias )
|
|
return;
|
|
|
|
|
|
ImageAliasData_t *pImageData = s_pDynamicTextures->GetImageAliasData( pAlias );
|
|
if ( s_pDynamicTextures->IsErrorImageAliasData( pImageData ) )
|
|
{
|
|
// If we didn't have an entry for this alias populate it now.
|
|
ImageAliasData_t *pImageData = GetImageAliasData( "errorImageAlias" );
|
|
ImageAliasData_t imageData;
|
|
imageData.m_XPos = pImageData->m_XPos;
|
|
imageData.m_YPos = pImageData->m_YPos;
|
|
imageData.m_Width = pImageData->m_Width;
|
|
imageData.m_Height = pImageData->m_Height;
|
|
imageData.m_szBaseTextureName = pImageData->m_szBaseTextureName;
|
|
imageData.m_Material = pImageData->m_Material;
|
|
imageData.m_bIsInSheet = pImageData->m_bIsInSheet;
|
|
imageData.m_nNodeIndex = pImageData->m_nNodeIndex;
|
|
s_pDynamicTextures->SetImageEntry( pAlias, imageData );
|
|
}
|
|
|
|
pImageData = s_pDynamicTextures->GetImageAliasData( pAlias );
|
|
pImageData->m_nRefCount++;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Associate this image alias name with a .vtf texture.
|
|
// This fxn loads the texture into the GameControls shader and makes a material
|
|
// for you
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::LoadImageAliasTexture( const char *pAlias, const char *pBaseTextureName )
|
|
{
|
|
if ( s_pDynamicTextures == NULL )
|
|
{
|
|
s_pDynamicTextures = new CGameUIDynamicTextures;
|
|
}
|
|
|
|
s_pDynamicTextures->LoadImageAlias( pAlias, pBaseTextureName );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Release all aliases associated with this menu from the packer
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::ReleaseImageAlias( const char *pAlias )
|
|
{
|
|
s_pDynamicTextures->ReleaseImageAlias( pAlias );
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Return the material bound to this image alias.
|
|
// If the texture was not found you will see the purple and black checkerboard
|
|
// error texture.
|
|
//-----------------------------------------------------------------------------
|
|
IMaterial *CGameUISystemMgr::GetImageAliasMaterial( const char *pAlias )
|
|
{
|
|
if ( s_pDynamicTextures == NULL )
|
|
return NULL;
|
|
|
|
return s_pDynamicTextures->GetImageAliasMaterial( pAlias );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
ImageAliasData_t *CGameUISystemMgr::GetImageAliasData( const char *pAlias )
|
|
{
|
|
if ( s_pDynamicTextures == NULL )
|
|
return NULL;
|
|
|
|
return s_pDynamicTextures->GetImageAliasData( pAlias );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Transform this texcoord into sheet coordinates.
|
|
// If the image is not in a sheet, does nothing.
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::TexCoordsToSheetTexCoords( const char *pAlias, Vector2D texCoords, Vector2D &sheetTexCoords )
|
|
{
|
|
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
|
|
if ( pImageData && pImageData->m_bIsInSheet )
|
|
{
|
|
// Transform texture coords to sheet texture coords.
|
|
int nSheetWidth = 0;
|
|
int nSheetHeight = 0;
|
|
s_pDynamicTextures->GetDynamicSheetSize( nSheetWidth, nSheetHeight );
|
|
Assert( nSheetWidth != 0 );
|
|
Assert( nSheetHeight != 0 );
|
|
float sampleWidth = ( ( (float)pImageData->m_Width - 1 ) / (float)nSheetWidth );
|
|
float sampleHeight = ( ( (float)pImageData->m_Height - 1 ) / (float)nSheetHeight );
|
|
float left = (pImageData->m_XPos + 0.5f) / (float)nSheetWidth;
|
|
float top = (pImageData->m_YPos + 0.5f) / (float)nSheetHeight;
|
|
|
|
sheetTexCoords.x = left + ( texCoords.x * sampleWidth );
|
|
sheetTexCoords.y = top + ( texCoords.y * sampleHeight );
|
|
|
|
Assert( sheetTexCoords.x >= 0 );
|
|
Assert( sheetTexCoords.x <= 1 );
|
|
Assert( sheetTexCoords.y >= 0 );
|
|
Assert( sheetTexCoords.y <= 1 );
|
|
}
|
|
else
|
|
{
|
|
sheetTexCoords.x = texCoords.x;
|
|
sheetTexCoords.y = texCoords.y;
|
|
}
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::DrawDynamicTexture( const char *pAlias, int x, int y )
|
|
{
|
|
if ( s_pDynamicTextures == NULL )
|
|
return;
|
|
|
|
s_pDynamicTextures->DrawDynamicTexture( pAlias, x, y );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
Vector2D CGameUISystemMgr::CursorToStage( Vector2D cursorPos )
|
|
{
|
|
Vector2D stageCoords;
|
|
Vector2D stageSize;
|
|
m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
|
|
|
|
// cursor is in viewport coords.
|
|
stageCoords.x = cursorPos.x * (stageSize.x/m_Viewport.width) - stageSize.x/2;
|
|
stageCoords.y = cursorPos.y * (stageSize.y/m_Viewport.height) - stageSize.y/2;
|
|
|
|
return stageCoords;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::ShowCursorCoords()
|
|
{
|
|
if ( !m_pCursorText )
|
|
{
|
|
m_pCursorText = new CGameText( "cursorcoords" );
|
|
Vector2D stageSize;
|
|
m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
|
|
m_ActiveMenuList[0]->Definition().AddGraphicToLayer( m_pCursorText, SUBLAYER_FONT );
|
|
}
|
|
|
|
int x, y;
|
|
g_pInputGameUI->GetCursorPos( x, y );
|
|
Vector2D coords = CursorToStage( Vector2D( x, y ));
|
|
m_pCursorText->SetCenter( coords.x, coords.y );
|
|
static color32 color;
|
|
color.r = rand()%256;
|
|
color.g = rand()%256;
|
|
color.b = rand()%256;
|
|
color.a = 255;
|
|
m_pCursorText->SetColor( color );
|
|
//pText->SetPos( -(stageSize.x/2)+5, (stageSize.y/2) - 20 );
|
|
CFmtStr szCursorMsg( "Cursor Position: %.0f, %.0f", coords.x, coords.y );
|
|
m_pCursorText->SetText( szCursorMsg.Access() );
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void CGameUISystemMgr::ShowGraphicName()
|
|
{
|
|
// Find the graphic directly under the cursor.
|
|
CGameGraphic *pGraphic = NULL;
|
|
int x, y;
|
|
g_pInputGameUI->GetCursorPos( x, y );
|
|
|
|
for ( int i = m_ActiveMenuList.Count() - 1; i >= 0; --i )
|
|
{
|
|
pGraphic = m_ActiveMenuList[i]->Definition().GetGraphic( x, y );
|
|
if ( pGraphic )
|
|
break;
|
|
}
|
|
|
|
if ( pGraphic == NULL )
|
|
{
|
|
if ( m_pCursorText )
|
|
{
|
|
CFmtStr szCursorMsg( "");
|
|
m_pCursorText->SetText( szCursorMsg.Access() );
|
|
}
|
|
return;
|
|
}
|
|
|
|
if ( !m_pCursorText )
|
|
{
|
|
m_pCursorText = new CGameText( "cursorcoords" );
|
|
Vector2D stageSize;
|
|
m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
|
|
m_ActiveMenuList[0]->Definition().AddGraphicToLayer( m_pCursorText, SUBLAYER_FONT );
|
|
}
|
|
|
|
|
|
Vector2D coords = CursorToStage( Vector2D( x, y ));
|
|
m_pCursorText->SetCenter( coords.x, coords.y );
|
|
static color32 color;
|
|
color.r = rand()%256;
|
|
color.g = rand()%256;
|
|
color.b = rand()%256;
|
|
color.a = 255;
|
|
m_pCursorText->SetColor( color );
|
|
//pText->SetPos( -(stageSize.x/2)+5, (stageSize.y/2) - 20 );
|
|
|
|
CFmtStr szCursorMsg( "Graphic name: %s", pGraphic->GetName() );
|
|
m_pCursorText->SetText( szCursorMsg.Access() );
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|