Counter Strike : Global Offensive Source Code
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

  1. //===== Copyright � 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //===========================================================================//
  7. #include "gameuisystemmgr.h"
  8. #include "soundsystem/isoundsystem.h"
  9. #include "SoundEmitterSystem/isoundemittersystembase.h"
  10. #include "gameuisystem.h"
  11. #include "tier2/fileutils.h"
  12. #include "rendersystem/irenderdevice.h"
  13. #include "rendersystem/irendercontext.h"
  14. #include "inputgameui.h"
  15. #include "gameuisystemsurface.h"
  16. #include "inputsystem/iinputsystem.h"
  17. #include "gamelayer.h"
  18. #include "gameuiscriptsystem.h"
  19. #include "inputsystem/iinputstacksystem.h"
  20. #include "fmtstr.h"
  21. #include "gametext.h"
  22. #undef PlaySound
  23. // memdbgon must be the last include file in a .cpp file!!!
  24. #include "tier0/memdbgon.h"
  25. static CGameUIDynamicTextures *s_pDynamicTextures = NULL;
  26. void OnRestore( int nChangeFlags )
  27. {
  28. if ( s_pDynamicTextures != NULL )
  29. {
  30. s_pDynamicTextures->OnRestore( nChangeFlags );
  31. }
  32. }
  33. //
  34. // MISC UTILS
  35. //
  36. class CGameUIMiscUtils : public IGameUIMiscUtils
  37. {
  38. public:
  39. virtual bool PointTriangleHitTest( Vector2D tringleVert0, Vector2D tringleVert1, Vector2D tringleVert2, Vector2D point )
  40. {
  41. return ::PointTriangleHitTest( tringleVert0, tringleVert1, tringleVert2, point );
  42. }
  43. }
  44. g_GameUIMiscUtils;
  45. IGameUIMiscUtils *g_pGameUIMiscUtils = &g_GameUIMiscUtils;
  46. //-----------------------------------------------------------------------------
  47. // Default game ui sound playback implementation
  48. //-----------------------------------------------------------------------------
  49. class CDefaultGameUISoundPlayback : public IGameUISoundPlayback
  50. {
  51. public:
  52. void *EmitSound( const char *pSoundName )
  53. {
  54. if ( !g_pSoundSystem )
  55. return NULL;
  56. // Ensure the sound is valid
  57. int nSoundIndex = g_pSoundEmitterSystem->GetSoundIndex( pSoundName );
  58. if ( !g_pSoundEmitterSystem->IsValidIndex( nSoundIndex ) )
  59. {
  60. Warning( "Attempted to play invalid sound \"%s\"\n", pSoundName );
  61. return NULL;
  62. }
  63. const char *pSourceFile = g_pSoundEmitterSystem->GetSourceFileForSound( nSoundIndex );
  64. if ( !Q_stristr( pSourceFile, "game_sounds_ui.txt" ) )
  65. {
  66. Warning( "Attempted to play invalid sound \"%s\". This sound must be defined\n"
  67. "in game_sounds_ui.txt but was defined in \"%s\" instead.\n", pSoundName, pSourceFile );
  68. return NULL;
  69. }
  70. // Pull data from parameters
  71. CSoundParameters params;
  72. HSOUNDSCRIPTHASH handle = SOUNDEMITTER_INVALID_HASH;
  73. if ( !g_pSoundEmitterSystem->GetParametersForSoundEx( pSoundName, handle, params, GENDER_NONE, true ) )
  74. return NULL;
  75. if ( !params.soundname[0] )
  76. return NULL;
  77. char pFileName[ MAX_PATH ];
  78. Q_snprintf( pFileName, sizeof(pFileName), "sound/%s", params.soundname );
  79. CAudioSource *pAudioSource = g_pSoundSystem->FindOrAddSound( pFileName );
  80. if ( !pAudioSource )
  81. return NULL;
  82. // NOTE: We're currently ignoring the sound delay time from the parameters,
  83. // as well as a bunch of other parameters. Oh well.
  84. CAudioMixer *pMixer = NULL;
  85. g_pSoundSystem->PlaySound( pAudioSource, params.volume, &pMixer );
  86. return pAudioSource;
  87. }
  88. void StopSound( void *pSoundHandle )
  89. {
  90. if ( !pSoundHandle || !g_pSoundSystem )
  91. return;
  92. CAudioSource *pAudioSource = (CAudioSource*)pSoundHandle;
  93. Assert( pAudioSource );
  94. CAudioMixer *pMixer = g_pSoundSystem->FindMixer( pAudioSource );
  95. g_pSoundSystem->StopSound( pMixer );
  96. }
  97. };
  98. static CDefaultGameUISoundPlayback s_DefaultGameUISoundPlayback;
  99. //-----------------------------------------------------------------------------
  100. // Default implementation of gameui system mgr
  101. //-----------------------------------------------------------------------------
  102. static CGameUISystemMgr s_GameUISystemMgr;
  103. CGameUISystemMgr *g_pGameUISystemMgrImpl = &s_GameUISystemMgr;
  104. void LinkGameControlsLib()
  105. {
  106. // This function is required for the linker to include CGameUISystemMgr
  107. }
  108. //-----------------------------------------------------------------------------
  109. // Used to allow us to install the game ui system into the list of app systems
  110. // that the client wants the engine to initialize
  111. //-----------------------------------------------------------------------------
  112. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CGameUISystemMgr, IGameUISystemMgr, GAMEUISYSTEMMGR_INTERFACE_VERSION, s_GameUISystemMgr );
  113. //-----------------------------------------------------------------------------
  114. // shader programs
  115. //-----------------------------------------------------------------------------
  116. static const char s_pVertexShader[] =
  117. "float4 v4OffsetScale : register( c0 ); "
  118. "float4 v4InstanceCount : register( c255 ); "
  119. "struct VS_INPUT "
  120. "{ "
  121. " float3 vPos : POSITION0; "
  122. " float4 vColor : COLOR0; "
  123. " float2 vTexCoord : TEXCOORD0; "
  124. "}; "
  125. " "
  126. "struct VS_OUTPUT "
  127. "{ "
  128. " float4 vColor : COLOR0; "
  129. " float2 vTexCoord : TEXCOORD0; "
  130. " float4 projPos : POSITION0; "
  131. "}; "
  132. " "
  133. "VS_OUTPUT main( const VS_INPUT v ) "
  134. "{ "
  135. " VS_OUTPUT o = ( VS_OUTPUT )0; "
  136. " "
  137. " o.projPos.xy = 2.0f * ( v.vPos.xy - v4OffsetScale.xy ) / ( v4OffsetScale.zw ) - float2( 1.0f, 1.0f );"
  138. " o.projPos.y *= -1.0f; "
  139. " o.projPos.z = 1; "
  140. " o.projPos.w = 1; "
  141. " o.vColor = v.vColor; "
  142. " o.vTexCoord = v.vTexCoord; "
  143. " return o; "
  144. "} "
  145. "";
  146. static const char s_pPixelShader[] =
  147. "struct PS_INPUT "
  148. "{ "
  149. " float4 vColor : COLOR0; "
  150. " float2 vTexCoord : TEXCOORD0; "
  151. "}; "
  152. " "
  153. "sampler BaseTextureSampler : register( s0 ); "
  154. "float4 main( const PS_INPUT i ) : COLOR "
  155. "{ "
  156. " return i.vColor * tex2D( BaseTextureSampler, i.vTexCoord ); "
  157. "} "
  158. "";
  159. static RenderInputLayoutField_t s_pGameUILayout[] =
  160. {
  161. DEFINE_PER_VERTEX_FIELD( 0, "position", 0, GameUIVertex_t, m_vecPosition )
  162. DEFINE_PER_VERTEX_FIELD( 0, "color", 0, GameUIVertex_t, m_color )
  163. DEFINE_PER_VERTEX_FIELD( 0, "texcoord", 0, GameUIVertex_t, m_vecTexCoord )
  164. };
  165. IScriptManager *g_pScriptManager;
  166. //-----------------------------------------------------------------------------
  167. // Inherited from IAppSystem
  168. //-----------------------------------------------------------------------------
  169. bool CGameUISystemMgr::Connect( CreateInterfaceFn factory )
  170. {
  171. if ( !BaseClass::Connect( factory ) )
  172. return false;
  173. g_pScriptManager = (IScriptManager *)factory( VSCRIPT_INTERFACE_VERSION, NULL );
  174. if ( !g_pScriptManager )
  175. return false;
  176. return true;
  177. }
  178. void CGameUISystemMgr::Disconnect()
  179. {
  180. g_pScriptManager = NULL;
  181. BaseClass::Disconnect();
  182. }
  183. void *CGameUISystemMgr::QueryInterface( const char *pInterfaceName )
  184. {
  185. if (!Q_strncmp( pInterfaceName, GAMEUISYSTEMMGR_INTERFACE_VERSION, Q_strlen( GAMEUISYSTEMMGR_INTERFACE_VERSION ) + 1))
  186. return (IGameUISystemMgr*)this;
  187. return NULL;
  188. }
  189. //-----------------------------------------------------------------------------
  190. // Less function for use with CUtlMap and CUtlString keys
  191. //-----------------------------------------------------------------------------
  192. bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs )
  193. {
  194. return ( Q_stricmp( lhs, rhs ) < 0 );
  195. }
  196. //-----------------------------------------------------------------------------
  197. // Constructor
  198. //-----------------------------------------------------------------------------
  199. CGameUISystemMgr::CGameUISystemMgr() :
  200. m_MenuSoundMap( UtlStringLessFunc ),
  201. m_ScreenControllerMap( UtlStringLessFunc ),
  202. m_GraphicClassMap( UtlStringLessFunc )
  203. {
  204. m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
  205. m_hVertexShader = RENDER_SHADER_HANDLE_INVALID;
  206. m_hPixelShader = RENDER_SHADER_HANDLE_INVALID;
  207. m_hConstBuffer = CONSTANT_BUFFER_HANDLE_INVALID;
  208. m_Viewport.x = 0;
  209. m_Viewport.y = 0;
  210. m_Viewport.width = 0;
  211. m_Viewport.height = 0;
  212. m_nWindowWidth = 0;
  213. m_nWindowHeight = 0;
  214. m_flCurrentTime = DmeTime_t(0);
  215. m_Scheme = NULL;
  216. m_RequestedKeyFocus = NULL;
  217. m_bForceFocusUpdate = false;
  218. m_bUseGameInputQueue = false;
  219. m_hInputContext = INPUT_CONTEXT_HANDLE_INVALID;
  220. m_pSoundPlayback = &s_DefaultGameUISoundPlayback;
  221. m_bVisible = true;
  222. m_bSetReleaseTimer = false;
  223. m_ReleaseStartTime = DmeTime_t(0);
  224. m_ReleaseTime = DmeTime_t(0);
  225. if ( !g_pGameUISystemMgr )
  226. g_pGameUISystemMgr = this;
  227. m_pCursorText = NULL;
  228. }
  229. //-----------------------------------------------------------------------------
  230. // Destructor
  231. //-----------------------------------------------------------------------------
  232. CGameUISystemMgr::~CGameUISystemMgr()
  233. {
  234. if ( m_pCursorText )
  235. {
  236. delete m_pCursorText;
  237. }
  238. }
  239. //-----------------------------------------------------------------------------
  240. // Initialize
  241. //-----------------------------------------------------------------------------
  242. static AppSystemInfo_t s_pDependencies[] =
  243. {
  244. { "vstdlib.dll", EVENTSYSTEM_INTERFACE_VERSION },
  245. { "vscript.dll", VSCRIPT_INTERFACE_VERSION },
  246. { "inputsystem.dll", INPUTSYSTEM_INTERFACE_VERSION },
  247. { "inputsystem.dll", INPUTSTACKSYSTEM_INTERFACE_VERSION },
  248. { "soundemittersystem.dll", SOUNDEMITTERSYSTEM_INTERFACE_VERSION },
  249. { NULL, NULL }
  250. };
  251. const AppSystemInfo_t* CGameUISystemMgr::GetDependencies()
  252. {
  253. return s_pDependencies;
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Initialize
  257. //-----------------------------------------------------------------------------
  258. InitReturnVal_t CGameUISystemMgr::Init( )
  259. {
  260. m_bForceFocusUpdate = false;
  261. m_bUseGameInputQueue = false;
  262. m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
  263. m_hInputContext = INPUT_CONTEXT_HANDLE_INVALID;
  264. m_pSoundPlayback = &s_DefaultGameUISoundPlayback;
  265. InitReturnVal_t nRetVal = BaseClass::Init();
  266. if ( nRetVal != INIT_OK )
  267. return nRetVal;
  268. g_pInputGameUI->Init();
  269. if ( g_pRenderDevice )
  270. {
  271. m_hInputLayout = g_pRenderDevice->CreateInputLayout( "GameUILayout", ARRAYSIZE( s_pGameUILayout ), s_pGameUILayout );
  272. m_hVertexShader = g_pRenderDevice->CreateShader( RENDER_VERTEX_SHADER, s_pVertexShader, sizeof(s_pVertexShader), g_pRenderDevice->GetShaderVersionString(RENDER_VERTEX_SHADER) );
  273. m_hPixelShader = g_pRenderDevice->CreateShader( RENDER_PIXEL_SHADER, s_pPixelShader, sizeof(s_pPixelShader), g_pRenderDevice->GetShaderVersionString(RENDER_PIXEL_SHADER) );
  274. m_hConstBuffer = g_pRenderDevice->CreateConstantBuffer( 4 * sizeof( float ) );
  275. Assert( m_hVertexShader != RENDER_SHADER_HANDLE_INVALID );
  276. Assert( m_hPixelShader != RENDER_SHADER_HANDLE_INVALID );
  277. }
  278. g_pGameUISystemSurface->Init();
  279. // Tell the input system to generate UI events
  280. g_pInputSystem->AddUIEventListener();
  281. m_Scheme = NULL;
  282. SetViewportSize( 1024, 768 );
  283. SetWindowSize( 1024, 768 );
  284. m_bVisible = true;
  285. m_RequestedKeyFocus = NULL;
  286. m_flCurrentTime = DmeTime_t(0);
  287. m_bSetReleaseTimer = false;
  288. m_ReleaseTime = DmeTime_t(0);
  289. s_pDynamicTextures = new CGameUIDynamicTextures;
  290. // Load in a default scheme
  291. if (!g_pGameUISchemeManager->LoadSchemeFromFile( "resource/BoxRocket.res", "GameUIDefaultScheme" ))
  292. {
  293. Assert( 0 );
  294. }
  295. // Dynamic textures not yet supported for source 2
  296. if ( g_pMaterialSystem )
  297. {
  298. g_pMaterialSystem->AddRestoreFunc( OnRestore );
  299. }
  300. return INIT_OK;
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Init any render targets needed by the UI.
  304. //-----------------------------------------------------------------------------
  305. void CGameUISystemMgr::InitRenderTargets()
  306. {
  307. s_pDynamicTextures->InitRenderTargets();
  308. }
  309. IMaterialProxy *CGameUISystemMgr::CreateProxy( const char *proxyName )
  310. {
  311. if ( s_pDynamicTextures )
  312. {
  313. return s_pDynamicTextures->CreateProxy( proxyName );
  314. }
  315. return NULL;
  316. }
  317. //-----------------------------------------------------------------------------
  318. // Shutdown
  319. //-----------------------------------------------------------------------------
  320. void CGameUISystemMgr::Shutdown()
  321. {
  322. if ( g_pMaterialSystem )
  323. {
  324. g_pMaterialSystem->RemoveRestoreFunc( OnRestore );
  325. }
  326. if ( s_pDynamicTextures )
  327. {
  328. delete s_pDynamicTextures;
  329. }
  330. if ( g_pRenderDevice )
  331. {
  332. g_pRenderDevice->DestroyConstantBuffer( m_hConstBuffer );
  333. g_pRenderDevice->DestroyShader( RENDER_PIXEL_SHADER, m_hPixelShader );
  334. g_pRenderDevice->DestroyShader( RENDER_VERTEX_SHADER, m_hVertexShader );
  335. g_pRenderDevice->DestroyInputLayout( m_hInputLayout );
  336. m_hInputLayout = RENDER_INPUT_LAYOUT_INVALID;
  337. }
  338. // release all menus.
  339. ReleaseAllGameUIScreens();
  340. g_pGameUISystemSurface->Shutdown();
  341. // Tell the input system we no longer need UI events
  342. g_pInputSystem->RemoveUIEventListener();
  343. BaseClass::Shutdown();
  344. }
  345. //-----------------------------------------------------------------------------
  346. // Set visibility of the entire gameui.
  347. //-----------------------------------------------------------------------------
  348. void CGameUISystemMgr::SetGameUIVisible( bool bVisible )
  349. {
  350. m_bVisible = bVisible;
  351. }
  352. //-----------------------------------------------------------------------------
  353. //
  354. //-----------------------------------------------------------------------------
  355. void CGameUISystemMgr::UseGameInputSystemEventQueue( bool bEnable )
  356. {
  357. m_bUseGameInputQueue = bEnable;
  358. }
  359. //-----------------------------------------------------------------------------
  360. //
  361. //-----------------------------------------------------------------------------
  362. void CGameUISystemMgr::RegisterInputEvent( const InputEvent_t &iEvent )
  363. {
  364. Assert( m_bUseGameInputQueue );
  365. m_InputQueue.AddToTail( iEvent );
  366. }
  367. //-----------------------------------------------------------------------------
  368. //
  369. //-----------------------------------------------------------------------------
  370. void CGameUISystemMgr::SendEventToAllScreens( KeyValues *kvGlobalEvent )
  371. {
  372. KeyValues::AutoDelete autodelete( kvGlobalEvent );
  373. for ( int j = 0; j < m_ActiveMenuList.Count(); ++j )
  374. {
  375. if ( m_bVisible && m_ActiveMenuList[j]->Definition().GetVisible() )
  376. {
  377. m_ActiveMenuList[j]->ExecuteScript( kvGlobalEvent );
  378. }
  379. }
  380. }
  381. void CGameUISystemMgr::PostEventToAllScreens( KeyValues *kvGlobalEvent )
  382. {
  383. m_GameUIEventMainQueue.AddToTail( kvGlobalEvent );
  384. }
  385. //-----------------------------------------------------------------------------
  386. // Return true if any menu is visible.
  387. //-----------------------------------------------------------------------------
  388. bool CGameUISystemMgr::IsMenuVisible() const
  389. {
  390. if ( !m_bVisible )
  391. return false;
  392. int nCount = m_ActiveMenuList.Count();
  393. for ( int i = 0; i < nCount; ++i )
  394. {
  395. if ( m_ActiveMenuList[i] )
  396. {
  397. if ( m_ActiveMenuList[i]->Definition().GetVisible() )
  398. return true;
  399. }
  400. }
  401. return false;
  402. }
  403. //-----------------------------------------------------------------------------
  404. // Specifies the input context handle to use to allow it to interoperate
  405. // with other input clients
  406. //-----------------------------------------------------------------------------
  407. void CGameUISystemMgr::SetInputContext( InputContextHandle_t hInputContext )
  408. {
  409. m_hInputContext = hInputContext;
  410. if ( m_hInputContext != INPUT_CONTEXT_HANDLE_INVALID )
  411. {
  412. g_pInputStackSystem->EnableInputContext( m_hInputContext, IsMenuVisible() );
  413. g_pInputStackSystem->SetCursorIcon( m_hInputContext, g_pInputSystem->GetStandardCursor( INPUT_CURSOR_ARROW ) );
  414. }
  415. }
  416. //-----------------------------------------------------------------------------
  417. // Returns the input context to use to control the cursor
  418. //-----------------------------------------------------------------------------
  419. InputContextHandle_t CGameUISystemMgr::GetInputContext( ) const
  420. {
  421. return m_hInputContext;
  422. }
  423. //-----------------------------------------------------------------------------
  424. // Allows you to control sound playback
  425. //-----------------------------------------------------------------------------
  426. void CGameUISystemMgr::SetSoundPlayback( IGameUISoundPlayback *pPlayback )
  427. {
  428. m_pSoundPlayback = pPlayback ? pPlayback : &s_DefaultGameUISoundPlayback;
  429. }
  430. //-----------------------------------------------------------------------------
  431. // Assign the scheme
  432. // This is because the scheme is needed to load text ui elements
  433. // so the def has to be able to assign it.
  434. //-----------------------------------------------------------------------------
  435. void CGameUISystemMgr::SetScheme( IGameUIScheme * scheme )
  436. {
  437. if ( m_Scheme && m_Scheme != scheme )
  438. {
  439. Warning( "Warning game menus do not all share the same scheme, text might look strange or fail to display.\n" );
  440. }
  441. m_Scheme = scheme;
  442. }
  443. //-----------------------------------------------------------------------------
  444. //
  445. //-----------------------------------------------------------------------------
  446. IGameUIScheme * CGameUISystemMgr::GetCurrentScheme()
  447. {
  448. // Currently the rendersystemtest text is being loaded with no scheme
  449. return m_Scheme;
  450. }
  451. //-----------------------------------------------------------------------------
  452. // Load a game UI into memory.
  453. // Return the menu id.
  454. //-----------------------------------------------------------------------------
  455. IGameUISystem * CGameUISystemMgr::LoadGameUIScreen( KeyValues *kvScreenLoadSettings )
  456. {
  457. if ( !kvScreenLoadSettings )
  458. return NULL;
  459. // Make a copy for safe modifications
  460. kvScreenLoadSettings = kvScreenLoadSettings->MakeCopy();
  461. KeyValues::AutoDelete autodelete_kvScreenLoadSettings( kvScreenLoadSettings );
  462. char const *szName = kvScreenLoadSettings->GetName();
  463. CFmtStr sFilename( "vguiedit/%s.gui", szName );
  464. const char *pFilename = sFilename;
  465. // Current menu
  466. IGameUISystem *pPreviousScreen = NULL;
  467. if ( m_ActiveMenuList.Count() )
  468. {
  469. pPreviousScreen = m_ActiveMenuList[ m_ActiveMenuList.Count() - 1 ];
  470. }
  471. // Always load a new instance of the menu
  472. CGameUISystem *pNewScreen = NULL;
  473. if ( !pNewScreen )
  474. {
  475. bool bSuccess = false;
  476. if ( szName && *szName )
  477. {
  478. CUtlBuffer buf( 0, 0, IsPlatformX360() ? 0 : CUtlBuffer::TEXT_BUFFER );
  479. if ( IsPlatformX360() )
  480. {
  481. buf.ActivateByteSwapping( true );
  482. }
  483. bSuccess = g_pFullFileSystem->ReadFile( pFilename, "GAME", buf );
  484. if ( bSuccess )
  485. {
  486. CGameUISystem *pGameUI = new CGameUISystem;
  487. bSuccess = pGameUI->LoadGameUIDefinition( buf, pFilename );
  488. if ( bSuccess )
  489. {
  490. pNewScreen = pGameUI;
  491. pGameUI->Init( kvScreenLoadSettings );
  492. }
  493. else
  494. {
  495. delete pGameUI;
  496. Warning( "Failed to load game ui file %s\n", pFilename );
  497. }
  498. }
  499. else
  500. {
  501. Warning( "Failed to read game ui file %s\n", pFilename );
  502. }
  503. }
  504. // Failed to read or load file. Load an empty ui instead.
  505. if ( !bSuccess )
  506. {
  507. CGameUISystem *pGameUI = new CGameUISystem;
  508. // for the name use the menu name of the file we tried to load
  509. char pFilenameStripped[ MAX_PATH ];
  510. int len = Q_strlen( pFilename );
  511. Q_StripExtension( pFilename, pFilenameStripped, len+1 );
  512. CUtlVector<char *> words;
  513. V_SplitString( pFilenameStripped, "/", words );
  514. int lastWord = words.Count() - 1;
  515. char *pMenuName = words[lastWord];
  516. pGameUI->LoadEmptyGameUI( pMenuName );
  517. pGameUI->Init( kvScreenLoadSettings );
  518. IGameUIScheme *pNewUIScheme = pGameUI->Definition().GetScheme();
  519. // Empty UI's should never stomp an already existing scheme.
  520. if ( !m_Scheme )
  521. {
  522. m_Scheme = pNewUIScheme;
  523. }
  524. pNewScreen = pGameUI;
  525. }
  526. }
  527. Assert( pNewScreen );
  528. pNewScreen->Definition().InitializeScripts();
  529. // Set it visible etc.
  530. pNewScreen->Definition().SetVisible( true );
  531. pNewScreen->Definition().SetAcceptInput( false );
  532. kvScreenLoadSettings->SetName( "OnLoad" );
  533. kvScreenLoadSettings->SetInt( "scripthandle", pNewScreen->GetScriptHandle() );
  534. pNewScreen->ExecuteScript( kvScreenLoadSettings );
  535. pNewScreen->Definition().SetAcceptInput( true );
  536. // Stack operation:
  537. char const *szDefaultStackOperation = "removeall";
  538. char const *szStackOperation = kvScreenLoadSettings->GetString( "stack", szDefaultStackOperation );
  539. if ( Q_stricmp( "append", szStackOperation ) != 0 )
  540. {
  541. // Take the old stack and move it into the m_ReleasedMenuList
  542. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  543. {
  544. m_ReleasedMenuList.AddToTail( m_ActiveMenuList[i] );
  545. }
  546. // Tell the previous stack to exit
  547. KeyValues *kvEventOnExit = new KeyValues( "OnExit");
  548. KeyValues::AutoDelete autodelete_kvEventOnExit( kvEventOnExit );
  549. for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
  550. {
  551. m_ReleasedMenuList[i]->Definition().SetAcceptInput( false );
  552. m_ReleasedMenuList[i]->ExecuteScript( kvEventOnExit );
  553. // null out requested focus for a released panel
  554. if ( m_RequestedKeyFocus && m_ReleasedMenuList[i]->Definition().HasGraphic( m_RequestedKeyFocus ) )
  555. {
  556. m_RequestedKeyFocus = NULL;
  557. }
  558. }
  559. m_ReleaseTime = DmeTime_t(0);
  560. m_bSetReleaseTimer = true;
  561. m_ActiveMenuList.RemoveAll();
  562. }
  563. // Push the new screen onto the stack
  564. m_ActiveMenuList.AddToTail( pNewScreen );
  565. // Init the newly loaded menu
  566. // ? not sure if we would want to merge load and init ?
  567. // we may control execution of scripts with passed in keyvalues
  568. kvScreenLoadSettings->SetName( "OnInit" );
  569. pNewScreen->ExecuteScript( kvScreenLoadSettings );
  570. return pNewScreen;
  571. }
  572. //-----------------------------------------------------------------------------
  573. //
  574. //-----------------------------------------------------------------------------
  575. void CGameUISystemMgr::ReleaseAllGameUIScreens()
  576. {
  577. while ( m_ActiveMenuList.Count() )
  578. {
  579. CGameUISystem *pTopScreen = m_ActiveMenuList.Tail();
  580. m_ActiveMenuList.RemoveMultipleFromTail( 1 );
  581. // need to release at safe point: pTopScreen->Release();
  582. DevMsg( "CGameUISystemMgr scheduled screen %p for release\n", pTopScreen );
  583. m_ReleasedMenuList.AddToTail( pTopScreen );
  584. m_ReleaseTime = DmeTime_t(0);
  585. m_bSetReleaseTimer = true;
  586. }
  587. }
  588. //-----------------------------------------------------------------------------
  589. //
  590. //-----------------------------------------------------------------------------
  591. void CGameUISystemMgr::OnScreenReleased( CGameUISystem *pScreen )
  592. {
  593. // Assuming that all the logic of transferring context/focus
  594. // from the released screen already happened
  595. if ( m_ActiveMenuList.FindAndRemove( pScreen ) )
  596. {
  597. DevWarning( "CGameUISystemMgr::OnScreenReleased( %p ) while screen is active!\n", pScreen );
  598. }
  599. // null out requested focus for a released panel
  600. if ( m_RequestedKeyFocus && pScreen->Definition().HasGraphic( m_RequestedKeyFocus ) )
  601. {
  602. m_RequestedKeyFocus = NULL;
  603. }
  604. }
  605. //-----------------------------------------------------------------------------
  606. // Process input.
  607. //-----------------------------------------------------------------------------
  608. void CGameUISystemMgr::RunFrame()
  609. {
  610. // All released menus are removed after a few seconds to allow them to clean up.
  611. if ( m_ReleaseTime > DmeTime_t( 5.0 ) && m_ReleasedMenuList.Count() )
  612. {
  613. for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
  614. {
  615. CGameUISystem *&pReleasedScreen = m_ReleasedMenuList[i];
  616. pReleasedScreen->Release();
  617. pReleasedScreen = NULL;
  618. }
  619. m_ReleasedMenuList.RemoveAll();
  620. }
  621. //
  622. // MAIN UPDATE LOOP
  623. //
  624. {
  625. // Regenerate if we should.
  626. if ( s_pDynamicTextures )
  627. {
  628. s_pDynamicTextures->RegenerateTexture( 0 );
  629. }
  630. // Update keyfocused and reset mouse and key states.
  631. g_pInputGameUI->RunFrame();
  632. m_RequestedKeyFocus = NULL;
  633. // Generate all gameui event messages
  634. // Run scripts to handle them.
  635. for ( int i = 0; i < m_GameUIEventMainQueue.Count(); ++i )
  636. {
  637. KeyValues *kvEvent = m_GameUIEventMainQueue[i];
  638. KeyValues::AutoDelete autodelete( kvEvent );
  639. for ( int j = 0; j < m_ActiveMenuList.Count(); ++j )
  640. {
  641. if ( m_bVisible && m_ActiveMenuList[j]->Definition().GetVisible() )
  642. {
  643. m_ActiveMenuList[j]->ExecuteScript( kvEvent );
  644. }
  645. }
  646. }
  647. m_GameUIEventMainQueue.RemoveAll();
  648. // Generate all input messages
  649. // this will generate all key and mouse events
  650. const InputEvent_t* pEvents = NULL;
  651. int nEventCount = 0;
  652. if ( m_bUseGameInputQueue )
  653. {
  654. nEventCount = m_InputQueue.Count();
  655. pEvents = m_InputQueue.Base();
  656. }
  657. else
  658. {
  659. nEventCount = g_pInputSystem->GetEventCount();
  660. pEvents = g_pInputSystem->GetEventData();
  661. }
  662. for ( int i = 0; i < nEventCount; ++i )
  663. {
  664. InputGameUIHandleInputEvent( pEvents[i] );
  665. }
  666. m_InputQueue.RemoveAll();
  667. // Specifically post the current mouse position as a message
  668. g_pInputGameUI->PostCursorMessage();
  669. if ( m_bForceFocusUpdate )
  670. {
  671. g_pInputGameUI->ForceInputFocusUpdate();
  672. m_bForceFocusUpdate = false;
  673. }
  674. g_pInputGameUI->ProcessEvents();
  675. // Run scripts.
  676. KeyValues *kvEventOnUpdate = new KeyValues( "OnUpdate" );
  677. KeyValues::AutoDelete autodelete_kvEventOnUpdate( kvEventOnUpdate );
  678. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  679. {
  680. if ( m_ActiveMenuList[i]->Definition().GetVisible() )
  681. {
  682. m_ActiveMenuList[i]->ExecuteScript( kvEventOnUpdate );
  683. }
  684. }
  685. for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
  686. {
  687. if ( m_ReleasedMenuList[i]->Definition().GetVisible() )
  688. {
  689. m_ReleasedMenuList[i]->ExecuteScript( kvEventOnUpdate );
  690. }
  691. }
  692. }
  693. // FIXME: Need better logic here.
  694. // Our input context is enabled if any menus are visible
  695. if ( m_hInputContext != INPUT_CONTEXT_HANDLE_INVALID )
  696. {
  697. g_pInputStackSystem->EnableInputContext( m_hInputContext, IsMenuVisible() );
  698. }
  699. }
  700. //-----------------------------------------------------------------------------
  701. //
  702. //-----------------------------------------------------------------------------
  703. void CGameUISystemMgr::RegisterScreenControllerFactory( char const *szControllerName, IGameUIScreenControllerFactory *pFactory )
  704. {
  705. m_ScreenControllerMap.InsertOrReplace( szControllerName, pFactory );
  706. }
  707. //-----------------------------------------------------------------------------
  708. //
  709. //-----------------------------------------------------------------------------
  710. IGameUIScreenControllerFactory *CGameUISystemMgr::GetScreenControllerFactory( char const *szControllerName )
  711. {
  712. ScreenControllerFactoryMap::IndexType_t idx = m_ScreenControllerMap.Find( szControllerName );
  713. if ( idx != m_ScreenControllerMap.InvalidIndex() )
  714. return m_ScreenControllerMap[idx];
  715. else
  716. return NULL;
  717. }
  718. //-----------------------------------------------------------------------------
  719. // Registers a factory to create a graphic class type (rect, text, hitarea)
  720. //-----------------------------------------------------------------------------
  721. void CGameUISystemMgr::RegisterGraphicClassFactory( char const *szGraphicClassName, IGameUIGraphicClassFactory *pFactory )
  722. {
  723. m_GraphicClassMap.InsertOrReplace( szGraphicClassName, pFactory );
  724. }
  725. //-----------------------------------------------------------------------------
  726. // Get the factory to create an instance of a graphic class ( rect, text, hitarea)
  727. //-----------------------------------------------------------------------------
  728. IGameUIGraphicClassFactory *CGameUISystemMgr::GetGraphicClassFactory( char const *szGraphicClassName )
  729. {
  730. GameUIGraphicClassFactoryMap::IndexType_t idx = m_GraphicClassMap.Find( szGraphicClassName );
  731. if ( idx != m_GraphicClassMap.InvalidIndex() )
  732. return m_GraphicClassMap[idx];
  733. else
  734. return NULL;
  735. }
  736. //-----------------------------------------------------------------------------
  737. //
  738. //-----------------------------------------------------------------------------
  739. IGameUISystemSurface * CGameUISystemMgr::GetSurface()
  740. {
  741. return g_pGameUISystemSurface;
  742. }
  743. //-----------------------------------------------------------------------------
  744. //
  745. //-----------------------------------------------------------------------------
  746. IGameUISchemeMgr * CGameUISystemMgr::GetSchemeMgr()
  747. {
  748. return g_pGameUISchemeManager;
  749. }
  750. //-----------------------------------------------------------------------------
  751. //
  752. //-----------------------------------------------------------------------------
  753. IGameUIMiscUtils * CGameUISystemMgr::GetMiscUtils()
  754. {
  755. return g_pGameUIMiscUtils;
  756. }
  757. //-----------------------------------------------------------------------------
  758. // ConCommand to trigger the menu for testing purposes
  759. //-----------------------------------------------------------------------------
  760. CON_COMMAND_F( ui_setmenus_hidden, "Hide the game ui", FCVAR_DEVELOPMENTONLY )
  761. {
  762. g_pGameUISystemMgrImpl->SetGameUIVisible( false );
  763. }
  764. //-----------------------------------------------------------------------------
  765. // Sets the current game UI menu.
  766. //-----------------------------------------------------------------------------
  767. CON_COMMAND_F( ui_setmenu, "Pass in a name; load it as the current game menu.", FCVAR_DEVELOPMENTONLY )
  768. {
  769. if ( args.ArgC() != 2 )
  770. {
  771. Msg( "ui_setmenu <name>\n" );
  772. return;
  773. }
  774. const char *szName = args[ 1 ];
  775. g_pGameUISystemMgrImpl->LoadGameUIScreen( KeyValues::AutoDeleteInline( new KeyValues( szName ) ) );
  776. }
  777. //-----------------------------------------------------------------------------
  778. // Source 1
  779. // Draw each gameui, note game uis render from back to front.
  780. // A newly loaded gameui goes in the front.
  781. //-----------------------------------------------------------------------------
  782. void CGameUISystemMgr::Render( const Rect_t &viewport, DmeTime_t flCurrentTime )
  783. {
  784. if ( m_bSetReleaseTimer )
  785. {
  786. m_ReleaseStartTime = flCurrentTime;
  787. m_bSetReleaseTimer = false;
  788. }
  789. else
  790. {
  791. m_ReleaseTime = flCurrentTime - m_ReleaseStartTime;
  792. }
  793. m_flCurrentTime = flCurrentTime;
  794. if ( !m_bVisible )
  795. return;
  796. // Check if the viewport size has changed.
  797. if ( ( m_Viewport.width != viewport.width ) ||
  798. ( m_Viewport.height != viewport.height ) )
  799. {
  800. m_Viewport.width = viewport.width;
  801. m_Viewport.height = viewport.height;
  802. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  803. int nWidth, nHeight;
  804. pRenderContext->GetWindowSize( nWidth, nHeight );
  805. SetWindowSize( nWidth, nHeight );
  806. // Update stage render transforms so the font size loaded is correct.
  807. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  808. {
  809. m_ActiveMenuList[i]->Definition().UpdateAspectRatio( viewport );
  810. }
  811. // Reload the fonts!
  812. g_pGameUISystemSurface->ResetFontCaches();
  813. }
  814. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  815. {
  816. m_ActiveMenuList[i]->Render( viewport );
  817. }
  818. // Render menus that are going away last (so they are in front)
  819. for ( int i = 0; i < m_ReleasedMenuList.Count(); ++i )
  820. {
  821. m_ReleasedMenuList[i]->Render( viewport );
  822. }
  823. }
  824. //-----------------------------------------------------------------------------
  825. // Source 2
  826. //-----------------------------------------------------------------------------
  827. void CGameUISystemMgr::Render( IRenderContext *pRenderContext, PlatWindow_t hWnd, const Rect_t &viewport, DmeTime_t flCurrentTime )
  828. {
  829. // Check if the viewport size has changed.
  830. if ( ( m_Viewport.width != viewport.width ) ||
  831. ( m_Viewport.height != viewport.height ) )
  832. {
  833. // Reload the fonts!
  834. m_Viewport.width = viewport.width;
  835. m_Viewport.height = viewport.height;
  836. int nWidth, nHeight;
  837. Plat_GetWindowClientSize( hWnd, &nWidth, &nHeight );
  838. SetWindowSize( nWidth, nHeight );
  839. // Update stage render transforms so the font size loaded is correct.
  840. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  841. {
  842. m_ActiveMenuList[i]->Definition().UpdateAspectRatio( viewport );
  843. }
  844. g_pGameUISystemSurface->ResetFontCaches();
  845. }
  846. m_flCurrentTime = flCurrentTime;
  847. for ( int i = 0; i < m_ActiveMenuList.Count(); ++i )
  848. {
  849. m_ActiveMenuList[i]->Render( pRenderContext, viewport );
  850. }
  851. }
  852. //-----------------------------------------------------------------------------
  853. // Get the current graphic that can accept mouse input and is under the mouse.
  854. //-----------------------------------------------------------------------------
  855. CHitArea *CGameUISystemMgr::GetMouseFocus()
  856. {
  857. return g_pInputGameUI->GetMouseFocus();
  858. }
  859. //-----------------------------------------------------------------------------
  860. // Get the graphic that can accept mouse input and is under the mouse.
  861. // We check from front to back.
  862. //-----------------------------------------------------------------------------
  863. CHitArea *CGameUISystemMgr::GetMouseFocus( int x, int y )
  864. {
  865. for ( int i = m_ActiveMenuList.Count()-1; i >=0; --i )
  866. {
  867. CHitArea *pGraphic = m_ActiveMenuList[i]->Definition().GetMouseFocus( x, y );
  868. if ( pGraphic )
  869. {
  870. return pGraphic;
  871. }
  872. }
  873. return NULL;
  874. }
  875. //-----------------------------------------------------------------------------
  876. // Get the graphic that can accept key input
  877. //-----------------------------------------------------------------------------
  878. CHitArea *CGameUISystemMgr::GetKeyFocus()
  879. {
  880. return g_pInputGameUI->GetKeyFocus();
  881. }
  882. //-----------------------------------------------------------------------------
  883. // Get the graphic that would like to accept key input
  884. //-----------------------------------------------------------------------------
  885. CHitArea *CGameUISystemMgr::GetRequestedKeyFocus()
  886. {
  887. return m_RequestedKeyFocus;
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose: Request key focus. If focus is changed play a sound.
  891. //-----------------------------------------------------------------------------
  892. void CGameUISystemMgr::RequestKeyFocus( CHitArea *pGraphic, KeyValues *args )
  893. {
  894. // Find the menu this graphic is in
  895. for ( int i = m_ActiveMenuList.Count()-1; i >=0; --i )
  896. {
  897. if ( m_ActiveMenuList[i]->Definition().GetVisible() )
  898. {
  899. if ( m_ActiveMenuList[i]->Definition().HasGraphic( pGraphic ) )
  900. {
  901. if ( !m_ActiveMenuList[i]->Definition().CanAcceptInput() )
  902. {
  903. Warning( "Key Focus requested for graphic %d that does not have input on in its menu!", pGraphic->GetName() );
  904. return;
  905. }
  906. }
  907. }
  908. }
  909. // Has nobody asked for it?
  910. if ( m_RequestedKeyFocus == NULL )
  911. {
  912. if ( pGraphic->IsGroup() )
  913. {
  914. // Find a hitarea inside.
  915. CGraphicGroup *pGroup = (CGraphicGroup *)pGraphic;
  916. CHitArea *pFocusGraphic = pGroup->GetKeyFocusRequestGraphic();
  917. if ( pFocusGraphic )
  918. {
  919. m_RequestedKeyFocus = pFocusGraphic;
  920. PlayMenuSound( args->GetString( "sound" ) );
  921. }
  922. }
  923. else
  924. {
  925. m_RequestedKeyFocus = pGraphic;
  926. PlayMenuSound( args->GetString( "sound" ) );
  927. }
  928. }
  929. }
  930. //-----------------------------------------------------------------------------
  931. // Purpose: Obtain the screen size.
  932. //-----------------------------------------------------------------------------
  933. void CGameUISystemMgr::GetScreenSize( int &nWide, int &nTall )
  934. {
  935. if ( !g_pMaterialSystem )
  936. {
  937. nWide = m_Viewport.width;
  938. nTall = m_Viewport.height;
  939. }
  940. else
  941. {
  942. Rect_t viewport;
  943. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  944. pRenderContext->GetViewport( viewport.x, viewport.y, nWide, nTall );
  945. }
  946. }
  947. //-----------------------------------------------------------------------------
  948. // Assumes all menus are full screen and same size right now.
  949. //-----------------------------------------------------------------------------
  950. void CGameUISystemMgr::GetScreenHeightForFontLoading( int &nTall )
  951. {
  952. Vector2D stageSize;
  953. if ( m_ActiveMenuList.Count() )
  954. {
  955. m_ActiveMenuList[0]->Definition().GetMaintainAspectRatioStageSize( stageSize );
  956. nTall = stageSize.y;
  957. }
  958. else
  959. {
  960. int nWide;
  961. GetScreenSize( nWide, nTall );
  962. }
  963. }
  964. //-----------------------------------------------------------------------------
  965. //
  966. //-----------------------------------------------------------------------------
  967. DmeTime_t CGameUISystemMgr::GetTime()
  968. {
  969. return m_flCurrentTime;
  970. }
  971. //-----------------------------------------------------------------------------
  972. // Purpose: If the hit graphic'c menu is set to have mouse focus change keyboard focus, update kb focus.
  973. //-----------------------------------------------------------------------------
  974. void CGameUISystemMgr::OnMouseFocusGained( CHitArea *mouseFocus )
  975. {
  976. for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
  977. {
  978. if ( m_ActiveMenuList[i]->Definition().GetVisible() &&
  979. m_ActiveMenuList[i]->Definition().HasGraphic( mouseFocus ) )
  980. {
  981. if ( m_ActiveMenuList[i]->Definition().IsMouseFocusEqualToKeyboardFocus() )
  982. {
  983. m_RequestedKeyFocus = mouseFocus;
  984. }
  985. return;
  986. }
  987. }
  988. }
  989. //-----------------------------------------------------------------------------
  990. // Purpose: If the hit graphic'c menu is set to have mouse focus change keyboard focus, update kb focus.
  991. //-----------------------------------------------------------------------------
  992. void CGameUISystemMgr::OnMouseFocusLost( CHitArea *mouseFocus )
  993. {
  994. for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
  995. {
  996. if ( m_ActiveMenuList[i]->Definition().GetVisible() &&
  997. m_ActiveMenuList[i]->Definition().HasGraphic( mouseFocus ) )
  998. {
  999. if ( m_ActiveMenuList[i]->Definition().IsMouseFocusEqualToKeyboardFocus() )
  1000. {
  1001. m_RequestedKeyFocus = NULL;
  1002. }
  1003. return;
  1004. }
  1005. }
  1006. }
  1007. //-----------------------------------------------------------------------------
  1008. // This fxn was called because nothing in the ui has keyfocus and a key was typed.
  1009. //-----------------------------------------------------------------------------
  1010. bool CGameUISystemMgr::OnKeyCodeTyped( const ButtonCode_t &code )
  1011. {
  1012. if ( code == KEY_TAB )
  1013. {
  1014. for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
  1015. {
  1016. CHitArea *pGraphic = m_ActiveMenuList[i]->Definition().GetNextFocus( g_pInputGameUI->GetKeyFocus() );
  1017. if ( pGraphic )
  1018. {
  1019. RequestKeyFocus( pGraphic );
  1020. //pGraphic->OnGainKeyFocus(); // hack to make on focus anims and script events play
  1021. return true;
  1022. }
  1023. }
  1024. }
  1025. return false;
  1026. }
  1027. //-----------------------------------------------------------------------------
  1028. //
  1029. //-----------------------------------------------------------------------------
  1030. bool CGameUISystemMgr::OnGameGraphicScriptEvent( CGameGraphic *pGraphic, KeyValues *kvEvent )
  1031. {
  1032. // Find the menu that owns this graphic
  1033. for ( int i = m_ActiveMenuList.Count()-1; i >= 0; --i )
  1034. {
  1035. if ( m_ActiveMenuList[i]->Definition().HasGraphic( pGraphic ) )
  1036. {
  1037. CUtlString sGraphicName;
  1038. m_ActiveMenuList[i]->Definition().BuildScopedGraphicName( sGraphicName, pGraphic );
  1039. kvEvent->SetString( "graphic", sGraphicName.Get() );
  1040. return m_ActiveMenuList[i]->ExecuteScript( kvEvent );
  1041. }
  1042. }
  1043. return false;
  1044. }
  1045. //-----------------------------------------------------------------------------
  1046. // This fxn was called because nothing in the ui has keyfocus and a key code was typed.
  1047. //-----------------------------------------------------------------------------
  1048. bool CGameUISystemMgr::OnKeyTyped( const wchar_t &unichar )
  1049. {
  1050. return false;
  1051. }
  1052. //-----------------------------------------------------------------------------
  1053. //
  1054. //-----------------------------------------------------------------------------
  1055. void CGameUISystemMgr::PlayMenuSound( const char *pSoundName )
  1056. {
  1057. if ( pSoundName == NULL || pSoundName[ 0 ] == '\0' )
  1058. return;
  1059. int index = m_MenuSoundMap.Find( pSoundName );
  1060. if ( index != m_MenuSoundMap.InvalidIndex() )
  1061. {
  1062. m_pSoundPlayback->StopSound( m_MenuSoundMap[index] );
  1063. }
  1064. else
  1065. {
  1066. index = m_MenuSoundMap.Insert( pSoundName, NULL );
  1067. }
  1068. m_MenuSoundMap[index] = m_pSoundPlayback->EmitSound( pSoundName );
  1069. }
  1070. //-----------------------------------------------------------------------------
  1071. //
  1072. //-----------------------------------------------------------------------------
  1073. void CGameUISystemMgr::StopMenuSound( const char *pSoundName )
  1074. {
  1075. int index = m_MenuSoundMap.Find( pSoundName );
  1076. if ( index == m_MenuSoundMap.InvalidIndex() )
  1077. return;
  1078. if ( m_MenuSoundMap[index] )
  1079. {
  1080. m_pSoundPlayback->StopSound( m_MenuSoundMap[index] );
  1081. m_MenuSoundMap[index] = NULL;
  1082. }
  1083. }
  1084. //-----------------------------------------------------------------------------
  1085. //
  1086. //-----------------------------------------------------------------------------
  1087. void CGameUISystemMgr::SetWindowSize( int nWidth, int nHeight )
  1088. {
  1089. m_nWindowWidth = nWidth;
  1090. m_nWindowHeight = nHeight;
  1091. }
  1092. //-----------------------------------------------------------------------------
  1093. //
  1094. //-----------------------------------------------------------------------------
  1095. void CGameUISystemMgr::GetWindowSize( int &nWidth, int &nHeight )
  1096. {
  1097. nWidth = m_nWindowWidth;
  1098. nHeight = m_nWindowHeight;
  1099. }
  1100. //-----------------------------------------------------------------------------
  1101. //
  1102. //-----------------------------------------------------------------------------
  1103. void CGameUISystemMgr::SetViewportSize( int nWidth, int nHeight )
  1104. {
  1105. m_Viewport.width = nWidth;
  1106. m_Viewport.height = nHeight;
  1107. }
  1108. //-----------------------------------------------------------------------------
  1109. //
  1110. //-----------------------------------------------------------------------------
  1111. void CGameUISystemMgr::GetViewportSize( int &nWidth, int &nHeight )
  1112. {
  1113. nWidth = m_Viewport.width;
  1114. nHeight = m_Viewport.height;
  1115. }
  1116. //-----------------------------------------------------------------------------
  1117. // Create an entry for this alias
  1118. //-----------------------------------------------------------------------------
  1119. void CGameUISystemMgr::InitImageAlias( const char *pAlias )
  1120. {
  1121. if ( s_pDynamicTextures == NULL )
  1122. {
  1123. s_pDynamicTextures = new CGameUIDynamicTextures;
  1124. }
  1125. if ( !pAlias || !*pAlias )
  1126. return;
  1127. ImageAliasData_t *pImageData = s_pDynamicTextures->GetImageAliasData( pAlias );
  1128. if ( s_pDynamicTextures->IsErrorImageAliasData( pImageData ) )
  1129. {
  1130. // If we didn't have an entry for this alias populate it now.
  1131. ImageAliasData_t *pImageData = GetImageAliasData( "errorImageAlias" );
  1132. ImageAliasData_t imageData;
  1133. imageData.m_XPos = pImageData->m_XPos;
  1134. imageData.m_YPos = pImageData->m_YPos;
  1135. imageData.m_Width = pImageData->m_Width;
  1136. imageData.m_Height = pImageData->m_Height;
  1137. imageData.m_szBaseTextureName = pImageData->m_szBaseTextureName;
  1138. imageData.m_Material = pImageData->m_Material;
  1139. imageData.m_bIsInSheet = pImageData->m_bIsInSheet;
  1140. imageData.m_nNodeIndex = pImageData->m_nNodeIndex;
  1141. s_pDynamicTextures->SetImageEntry( pAlias, imageData );
  1142. }
  1143. pImageData = s_pDynamicTextures->GetImageAliasData( pAlias );
  1144. pImageData->m_nRefCount++;
  1145. }
  1146. //-----------------------------------------------------------------------------
  1147. // Associate this image alias name with a .vtf texture.
  1148. // This fxn loads the texture into the GameControls shader and makes a material
  1149. // for you
  1150. //-----------------------------------------------------------------------------
  1151. void CGameUISystemMgr::LoadImageAliasTexture( const char *pAlias, const char *pBaseTextureName )
  1152. {
  1153. if ( s_pDynamicTextures == NULL )
  1154. {
  1155. s_pDynamicTextures = new CGameUIDynamicTextures;
  1156. }
  1157. s_pDynamicTextures->LoadImageAlias( pAlias, pBaseTextureName );
  1158. }
  1159. //-----------------------------------------------------------------------------
  1160. // Release all aliases associated with this menu from the packer
  1161. //-----------------------------------------------------------------------------
  1162. void CGameUISystemMgr::ReleaseImageAlias( const char *pAlias )
  1163. {
  1164. s_pDynamicTextures->ReleaseImageAlias( pAlias );
  1165. }
  1166. //-----------------------------------------------------------------------------
  1167. // Return the material bound to this image alias.
  1168. // If the texture was not found you will see the purple and black checkerboard
  1169. // error texture.
  1170. //-----------------------------------------------------------------------------
  1171. IMaterial *CGameUISystemMgr::GetImageAliasMaterial( const char *pAlias )
  1172. {
  1173. if ( s_pDynamicTextures == NULL )
  1174. return NULL;
  1175. return s_pDynamicTextures->GetImageAliasMaterial( pAlias );
  1176. }
  1177. //-----------------------------------------------------------------------------
  1178. //
  1179. //-----------------------------------------------------------------------------
  1180. ImageAliasData_t *CGameUISystemMgr::GetImageAliasData( const char *pAlias )
  1181. {
  1182. if ( s_pDynamicTextures == NULL )
  1183. return NULL;
  1184. return s_pDynamicTextures->GetImageAliasData( pAlias );
  1185. }
  1186. //-----------------------------------------------------------------------------
  1187. // Transform this texcoord into sheet coordinates.
  1188. // If the image is not in a sheet, does nothing.
  1189. //-----------------------------------------------------------------------------
  1190. void CGameUISystemMgr::TexCoordsToSheetTexCoords( const char *pAlias, Vector2D texCoords, Vector2D &sheetTexCoords )
  1191. {
  1192. ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
  1193. if ( pImageData && pImageData->m_bIsInSheet )
  1194. {
  1195. // Transform texture coords to sheet texture coords.
  1196. int nSheetWidth = 0;
  1197. int nSheetHeight = 0;
  1198. s_pDynamicTextures->GetDynamicSheetSize( nSheetWidth, nSheetHeight );
  1199. Assert( nSheetWidth != 0 );
  1200. Assert( nSheetHeight != 0 );
  1201. float sampleWidth = ( ( (float)pImageData->m_Width - 1 ) / (float)nSheetWidth );
  1202. float sampleHeight = ( ( (float)pImageData->m_Height - 1 ) / (float)nSheetHeight );
  1203. float left = (pImageData->m_XPos + 0.5f) / (float)nSheetWidth;
  1204. float top = (pImageData->m_YPos + 0.5f) / (float)nSheetHeight;
  1205. sheetTexCoords.x = left + ( texCoords.x * sampleWidth );
  1206. sheetTexCoords.y = top + ( texCoords.y * sampleHeight );
  1207. Assert( sheetTexCoords.x >= 0 );
  1208. Assert( sheetTexCoords.x <= 1 );
  1209. Assert( sheetTexCoords.y >= 0 );
  1210. Assert( sheetTexCoords.y <= 1 );
  1211. }
  1212. else
  1213. {
  1214. sheetTexCoords.x = texCoords.x;
  1215. sheetTexCoords.y = texCoords.y;
  1216. }
  1217. }
  1218. //-----------------------------------------------------------------------------
  1219. //
  1220. //-----------------------------------------------------------------------------
  1221. void CGameUISystemMgr::DrawDynamicTexture( const char *pAlias, int x, int y )
  1222. {
  1223. if ( s_pDynamicTextures == NULL )
  1224. return;
  1225. s_pDynamicTextures->DrawDynamicTexture( pAlias, x, y );
  1226. }
  1227. //-----------------------------------------------------------------------------
  1228. //
  1229. //-----------------------------------------------------------------------------
  1230. Vector2D CGameUISystemMgr::CursorToStage( Vector2D cursorPos )
  1231. {
  1232. Vector2D stageCoords;
  1233. Vector2D stageSize;
  1234. m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
  1235. // cursor is in viewport coords.
  1236. stageCoords.x = cursorPos.x * (stageSize.x/m_Viewport.width) - stageSize.x/2;
  1237. stageCoords.y = cursorPos.y * (stageSize.y/m_Viewport.height) - stageSize.y/2;
  1238. return stageCoords;
  1239. }
  1240. //-----------------------------------------------------------------------------
  1241. //
  1242. //-----------------------------------------------------------------------------
  1243. void CGameUISystemMgr::ShowCursorCoords()
  1244. {
  1245. if ( !m_pCursorText )
  1246. {
  1247. m_pCursorText = new CGameText( "cursorcoords" );
  1248. Vector2D stageSize;
  1249. m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
  1250. m_ActiveMenuList[0]->Definition().AddGraphicToLayer( m_pCursorText, SUBLAYER_FONT );
  1251. }
  1252. int x, y;
  1253. g_pInputGameUI->GetCursorPos( x, y );
  1254. Vector2D coords = CursorToStage( Vector2D( x, y ));
  1255. m_pCursorText->SetCenter( coords.x, coords.y );
  1256. static color32 color;
  1257. color.r = rand()%256;
  1258. color.g = rand()%256;
  1259. color.b = rand()%256;
  1260. color.a = 255;
  1261. m_pCursorText->SetColor( color );
  1262. //pText->SetPos( -(stageSize.x/2)+5, (stageSize.y/2) - 20 );
  1263. CFmtStr szCursorMsg( "Cursor Position: %.0f, %.0f", coords.x, coords.y );
  1264. m_pCursorText->SetText( szCursorMsg.Access() );
  1265. }
  1266. //-----------------------------------------------------------------------------
  1267. //
  1268. //-----------------------------------------------------------------------------
  1269. void CGameUISystemMgr::ShowGraphicName()
  1270. {
  1271. // Find the graphic directly under the cursor.
  1272. CGameGraphic *pGraphic = NULL;
  1273. int x, y;
  1274. g_pInputGameUI->GetCursorPos( x, y );
  1275. for ( int i = m_ActiveMenuList.Count() - 1; i >= 0; --i )
  1276. {
  1277. pGraphic = m_ActiveMenuList[i]->Definition().GetGraphic( x, y );
  1278. if ( pGraphic )
  1279. break;
  1280. }
  1281. if ( pGraphic == NULL )
  1282. {
  1283. if ( m_pCursorText )
  1284. {
  1285. CFmtStr szCursorMsg( "");
  1286. m_pCursorText->SetText( szCursorMsg.Access() );
  1287. }
  1288. return;
  1289. }
  1290. if ( !m_pCursorText )
  1291. {
  1292. m_pCursorText = new CGameText( "cursorcoords" );
  1293. Vector2D stageSize;
  1294. m_ActiveMenuList[0]->Definition().GetStageSize( stageSize );
  1295. m_ActiveMenuList[0]->Definition().AddGraphicToLayer( m_pCursorText, SUBLAYER_FONT );
  1296. }
  1297. Vector2D coords = CursorToStage( Vector2D( x, y ));
  1298. m_pCursorText->SetCenter( coords.x, coords.y );
  1299. static color32 color;
  1300. color.r = rand()%256;
  1301. color.g = rand()%256;
  1302. color.b = rand()%256;
  1303. color.a = 255;
  1304. m_pCursorText->SetColor( color );
  1305. //pText->SetPos( -(stageSize.x/2)+5, (stageSize.y/2) - 20 );
  1306. CFmtStr szCursorMsg( "Graphic name: %s", pGraphic->GetName() );
  1307. m_pCursorText->SetText( szCursorMsg.Access() );
  1308. }