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.

5140 lines
149 KiB

  1. //====== Copyright 1996-2005, Valve Corporation, All rights reserved. =======//
  2. //
  3. // Purpose: Implementation of the VGUI ISurface interface using the
  4. // material system to implement it
  5. //
  6. //=============================================================================//
  7. #define SUPPORT_CUSTOM_FONT_FORMAT
  8. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  9. #define _WIN32_WINNT 0x0500
  10. #endif
  11. #if defined( WIN32) && !defined( _X360 )
  12. #include <windows.h>
  13. #endif
  14. #ifdef OSX
  15. #include <Carbon/Carbon.h>
  16. #endif
  17. #ifdef LINUX
  18. #include <fontconfig/fontconfig.h>
  19. #endif
  20. #if defined( USE_SDL ) || defined(OSX)
  21. #include <appframework/ilaunchermgr.h>
  22. ILauncherMgr *g_pLauncherMgr = NULL;
  23. #endif
  24. #include "tier1/strtools.h"
  25. #include "tier0/icommandline.h"
  26. #include "tier0/dbg.h"
  27. #include "filesystem.h"
  28. #include <vgui/vgui.h>
  29. #include <color.h>
  30. #include "shaderapi/ishaderapi.h"
  31. #include "utlvector.h"
  32. #include "Clip2D.h"
  33. #include <vgui_controls/Panel.h>
  34. #include <vgui/IInput.h>
  35. #include <vgui/Point.h>
  36. #include "bitmap/imageformat.h"
  37. #include "vgui_surfacelib/texturedictionary.h"
  38. #include "Cursor.h"
  39. #include "Input.h"
  40. #include <vgui/IHTML.h>
  41. #include <vgui/IVGui.h>
  42. #include "vgui_surfacelib/fontmanager.h"
  43. #include "vgui_surfacelib/fonttexturecache.h"
  44. #include "MatSystemSurface.h"
  45. #include "inputsystem/iinputsystem.h"
  46. #include <vgui_controls/Controls.h>
  47. #include <vgui/ISystem.h>
  48. #include "icvar.h"
  49. #include "mathlib/mathlib.h"
  50. #include <vgui/ILocalize.h>
  51. #include "mathlib/vmatrix.h"
  52. #include <tier0/vprof.h>
  53. #include "materialsystem/itexture.h"
  54. #ifndef _PS3
  55. #include <malloc.h>
  56. #else
  57. #include <wctype.h>
  58. #endif
  59. #include "../vgui2/src/VPanel.h"
  60. #include <vgui/IInputInternal.h>
  61. #if defined( _X360 )
  62. #include "xbox/xbox_win32stubs.h"
  63. #endif
  64. #include "xbox/xboxstubs.h"
  65. #pragma warning( disable : 4706 )
  66. #include <vgui/IVguiMatInfo.h>
  67. #include <vgui/IVguiMatInfoVar.h>
  68. #include "materialsystem/imaterialvar.h"
  69. #include "memorybitmap.h"
  70. #include "valvefont.h"
  71. #pragma warning( default : 4706 )
  72. // memdbgon must be the last include file in a .cpp file!!!
  73. #include "tier0/memdbgon.h"
  74. #if defined( _GAMECONSOLE )
  75. #define MODEL_PANEL_RT_NAME "_rt_SmallFB0"
  76. #else // _GAMECONSOLE
  77. #define MODEL_PANEL_RT_NAME "_rt_FullScreen"
  78. #endif // !_GAMECONSOLE
  79. #define VPANEL_NORMAL ((vgui::SurfacePlat *) NULL)
  80. #define VPANEL_MINIMIZED ((vgui::SurfacePlat *) 0x00000001)
  81. using namespace vgui;
  82. static bool g_bSpewFocus = false;
  83. class CVguiMatInfoVar : public IVguiMatInfoVar
  84. {
  85. public:
  86. CVguiMatInfoVar( IMaterialVar *pMaterialVar )
  87. {
  88. m_pMaterialVar = pMaterialVar;
  89. }
  90. // from IVguiMatInfoVar
  91. virtual int GetIntValue ( void ) const
  92. {
  93. return m_pMaterialVar->GetIntValue();
  94. }
  95. virtual void SetIntValue ( int val )
  96. {
  97. m_pMaterialVar->SetIntValue( val );
  98. }
  99. private:
  100. IMaterialVar *m_pMaterialVar;
  101. };
  102. class CVguiMatInfo : public IVguiMatInfo
  103. {
  104. public:
  105. CVguiMatInfo( IMaterial *pMaterial )
  106. {
  107. m_pMaterial = pMaterial;
  108. }
  109. // from IVguiMatInfo
  110. virtual IVguiMatInfoVar* FindVarFactory( const char *varName, bool *found )
  111. {
  112. IMaterialVar *pMaterialVar = m_pMaterial->FindVar( varName, found );
  113. if ( pMaterialVar == NULL )
  114. return NULL;
  115. return new CVguiMatInfoVar( pMaterialVar );
  116. }
  117. virtual int GetNumAnimationFrames( void )
  118. {
  119. return m_pMaterial->GetNumAnimationFrames();
  120. }
  121. private:
  122. IMaterial *m_pMaterial;
  123. };
  124. //-----------------------------------------------------------------------------
  125. // Globals...
  126. //-----------------------------------------------------------------------------
  127. vgui::IInputInternal *g_pIInput;
  128. static bool g_bInDrawing;
  129. static CFontTextureCache g_FontTextureCache;
  130. //-----------------------------------------------------------------------------
  131. // Singleton instance
  132. //-----------------------------------------------------------------------------
  133. CMatSystemSurface g_MatSystemSurface;
  134. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CMatSystemSurface, ISurface,
  135. VGUI_SURFACE_INTERFACE_VERSION, g_MatSystemSurface );
  136. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CMatSystemSurface, ISchemeSurface,
  137. SCHEME_SURFACE_INTERFACE_VERSION, g_MatSystemSurface );
  138. #ifdef LINUX
  139. CUtlDict< CMatSystemSurface::font_entry, unsigned short > CMatSystemSurface::m_FontData;
  140. #endif
  141. //-----------------------------------------------------------------------------
  142. // Make sure the panel is the same size as the viewport
  143. //-----------------------------------------------------------------------------
  144. CMatEmbeddedPanel::CMatEmbeddedPanel() : BaseClass( NULL, "MatSystemTopPanel" )
  145. {
  146. SetPaintBackgroundEnabled( false );
  147. #if defined( _X360 )
  148. SetPos( 0, 0 );
  149. SetSize( GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );
  150. #endif
  151. }
  152. void CMatEmbeddedPanel::OnThink()
  153. {
  154. int x, y, width, height;
  155. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  156. pRenderContext->GetViewport( x, y, width, height );
  157. SetSize( width, height );
  158. SetPos( x, y );
  159. Repaint();
  160. }
  161. VPANEL CMatEmbeddedPanel::IsWithinTraverse(int x, int y, bool traversePopups)
  162. {
  163. VPANEL retval = BaseClass::IsWithinTraverse( x, y, traversePopups );
  164. if ( retval == GetVPanel() )
  165. return 0;
  166. return retval;
  167. }
  168. //-----------------------------------------------------------------------------
  169. // Constructor, destructor
  170. //-----------------------------------------------------------------------------
  171. CMatSystemSurface::CMatSystemSurface() : m_pEmbeddedPanel(NULL), m_pWhite(NULL), m_ContextAbsPos( 0, 0, ContextAbsPos_t::Less )
  172. {
  173. m_iBoundTexture = -1;
  174. m_nCurrReferenceValue = 0;
  175. m_bIn3DPaintMode = false;
  176. m_bDrawingIn3DWorld = false;
  177. m_PlaySoundFunc = NULL;
  178. m_bInThink = false;
  179. m_bAllowJavaScript = false;
  180. m_bAppDrivesInput = false;
  181. m_nLastInputPollCount = 0;
  182. m_flApparentDepth = STEREO_INVALID;
  183. m_hCurrentFont = NULL;
  184. m_pRestrictedPanel = NULL;
  185. m_bRestrictedPanelOverrodeAppModalPanel = false;
  186. m_bEnableInput = false;
  187. m_bNeedsKeyboard = false;
  188. m_bNeedsMouse = false;
  189. m_bUsingTempFullScreenBufferMaterial = false;
  190. m_nFullScreenBufferMaterialId = -1;
  191. m_nFullScreenBufferMaterialIgnoreAlphaId = -1;
  192. m_hInputContext = INPUT_CONTEXT_HANDLE_INVALID;
  193. memset( m_WorkSpaceInsets, 0, sizeof( m_WorkSpaceInsets ) );
  194. m_nBatchedCharVertCount = 0;
  195. g_FontTextureCache.SetPrefix( "vgui" );
  196. }
  197. CMatSystemSurface::~CMatSystemSurface()
  198. {
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Connect, disconnect...
  202. //-----------------------------------------------------------------------------
  203. bool CMatSystemSurface::Connect( CreateInterfaceFn factory )
  204. {
  205. if ( !BaseClass::Connect( factory ) )
  206. return false;
  207. if ( !g_pFullFileSystem )
  208. {
  209. Warning( "MatSystemSurface requires the file system to run!\n" );
  210. return false;
  211. }
  212. if ( !g_pMaterialSystem )
  213. {
  214. Warning( "MatSystemSurface requires the material system to run!\n" );
  215. return false;
  216. }
  217. if ( !g_pVGuiPanel )
  218. {
  219. Warning( "MatSystemSurface requires the vgui::IPanel system to run!\n" );
  220. return false;
  221. }
  222. g_pIInput = (IInputInternal *)factory( VGUI_INPUTINTERNAL_INTERFACE_VERSION, NULL );
  223. if ( !g_pIInput )
  224. {
  225. Warning( "MatSystemSurface requires the vgui::IInput system to run!\n" );
  226. return false;
  227. }
  228. if ( !g_pVGui )
  229. {
  230. Warning( "MatSystemSurface requires the vgui::IVGUI system to run!\n" );
  231. return false;
  232. }
  233. Assert( g_pVGuiSurface == this );
  234. // initialize vgui_control interfaces
  235. if ( !vgui::VGui_InitInterfacesList( "MATSURFACE", &factory, 1 ) )
  236. return false;
  237. #if defined( USE_SDL )
  238. g_pLauncherMgr = (ILauncherMgr *)factory( SDLMGR_INTERFACE_VERSION, NULL );
  239. #elif defined( OSX )
  240. g_pLauncherMgr = (ILauncherMgr *)factory( COCOAMGR_INTERFACE_VERSION, NULL );
  241. #endif
  242. return true;
  243. }
  244. void CMatSystemSurface::Disconnect()
  245. {
  246. g_pIInput = NULL;
  247. BaseClass::Disconnect();
  248. }
  249. //-----------------------------------------------------------------------------
  250. // Access to other interfaces...
  251. //-----------------------------------------------------------------------------
  252. void *CMatSystemSurface::QueryInterface( const char *pInterfaceName )
  253. {
  254. // We also implement the IMatSystemSurface interface
  255. if (!Q_strncmp( pInterfaceName, MAT_SYSTEM_SURFACE_INTERFACE_VERSION, Q_strlen(MAT_SYSTEM_SURFACE_INTERFACE_VERSION) + 1))
  256. return (IMatSystemSurface*)this;
  257. // We also implement the IMatSystemSurface interface
  258. if (!Q_strncmp( pInterfaceName, VGUI_SURFACE_INTERFACE_VERSION, Q_strlen(VGUI_SURFACE_INTERFACE_VERSION) + 1))
  259. return (vgui::ISurface*)this;
  260. // We also implement the ISchemeSurface interface
  261. if (!Q_strncmp( pInterfaceName, SCHEME_SURFACE_INTERFACE_VERSION, Q_strlen(SCHEME_SURFACE_INTERFACE_VERSION) + 1))
  262. return (ISchemeSurface*)this;
  263. return BaseClass::QueryInterface( pInterfaceName );
  264. }
  265. //-----------------------------------------------------------------------------
  266. // Get dependencies
  267. //-----------------------------------------------------------------------------
  268. static AppSystemInfo_t s_Dependencies[] =
  269. {
  270. { "localize" DLL_EXT_STRING, LOCALIZE_INTERFACE_VERSION },
  271. { "inputsystem" DLL_EXT_STRING, INPUTSTACKSYSTEM_INTERFACE_VERSION },
  272. { "materialsystem" DLL_EXT_STRING, MATERIAL_SYSTEM_INTERFACE_VERSION },
  273. { NULL, NULL }
  274. };
  275. const AppSystemInfo_t* CMatSystemSurface::GetDependencies()
  276. {
  277. return s_Dependencies;
  278. }
  279. //-----------------------------------------------------------------------------
  280. // Purpose:
  281. //-----------------------------------------------------------------------------
  282. void CMatSystemSurface::InitFullScreenBuffer( const char *pszRenderTargetName )
  283. {
  284. char pTemp[512];
  285. m_FullScreenBufferMaterial.Shutdown();
  286. m_FullScreenBufferMaterialIgnoreAlpha.Shutdown();
  287. // Set up a material with which to reference the final image for subsequent display using vgui
  288. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  289. pVMTKeyValues->SetString( "$basetexture", pszRenderTargetName );
  290. pVMTKeyValues->SetInt( "$nocull", 1 );
  291. pVMTKeyValues->SetInt( "$nofog", 1 );
  292. pVMTKeyValues->SetInt( "$ignorez", 1 );
  293. pVMTKeyValues->SetInt( "$translucent", 1 );
  294. Q_snprintf( pTemp, sizeof(pTemp), "VGUI_3DPaint_FullScreen_%s", pszRenderTargetName );
  295. m_FullScreenBufferMaterial.Init( pTemp, TEXTURE_GROUP_OTHER, pVMTKeyValues );
  296. m_FullScreenBufferMaterial->Refresh();
  297. pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  298. pVMTKeyValues->SetString( "$basetexture", pszRenderTargetName );
  299. pVMTKeyValues->SetInt( "$nocull", 1 );
  300. pVMTKeyValues->SetInt( "$nofog", 1 );
  301. pVMTKeyValues->SetInt( "$ignorez", 1 );
  302. Q_snprintf( pTemp, sizeof(pTemp), "VGUI_3DPaint_FullScreen_IgnoreAlpha_%s", pszRenderTargetName );
  303. m_FullScreenBufferMaterialIgnoreAlpha.Init( pTemp, TEXTURE_GROUP_OTHER, pVMTKeyValues );
  304. m_FullScreenBufferMaterialIgnoreAlpha->Refresh();
  305. if ( m_nFullScreenBufferMaterialId != -1 )
  306. {
  307. DestroyTextureID( m_nFullScreenBufferMaterialId );
  308. }
  309. m_nFullScreenBufferMaterialId = -1;
  310. if ( m_nFullScreenBufferMaterialIgnoreAlphaId != -1 )
  311. {
  312. DestroyTextureID( m_nFullScreenBufferMaterialIgnoreAlphaId );
  313. }
  314. m_nFullScreenBufferMaterialIgnoreAlphaId = -1;
  315. m_FullScreenBuffer.Shutdown();
  316. m_FullScreenBufferName = pszRenderTargetName;
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Initialization and shutdown...
  320. //-----------------------------------------------------------------------------
  321. InitReturnVal_t CMatSystemSurface::Init( void )
  322. {
  323. InitReturnVal_t nRetVal = BaseClass::Init();
  324. if ( nRetVal != INIT_OK )
  325. return nRetVal;
  326. MathLib_Init( 2.2f, 2.2f, 0.0f, 2.0f, true, true, true, true );
  327. g_pLocalize->SetTextQuery( this );
  328. // Allocate a white material
  329. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  330. pVMTKeyValues->SetInt( "$vertexcolor", 1 );
  331. pVMTKeyValues->SetInt( "$vertexalpha", 1 );
  332. pVMTKeyValues->SetInt( "$ignorez", 1 );
  333. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  334. pVMTKeyValues->SetInt( "$nocull", 1 );
  335. m_pWhite.Init( "VGUI_White", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  336. InitFullScreenBuffer( MODEL_PANEL_RT_NAME );
  337. m_DrawColor[0] = m_DrawColor[1] = m_DrawColor[2] = m_DrawColor[3] = 255;
  338. m_nTranslateX = m_nTranslateY = 0;
  339. EnableScissor( false );
  340. SetScissorRect( 0, 0, 100000, 100000 );
  341. m_flAlphaMultiplier = 1.0f;
  342. // By default, use the default embedded panel
  343. m_pDefaultEmbeddedPanel = new CMatEmbeddedPanel;
  344. SetEmbeddedPanel( m_pDefaultEmbeddedPanel->GetVPanel() );
  345. m_iBoundTexture = -1;
  346. // Initialize font info..
  347. m_pDrawTextPos[0] = m_pDrawTextPos[1] = 0;
  348. m_DrawTextColor[0] = m_DrawTextColor[1] = m_DrawTextColor[2] = m_DrawTextColor[3] = 255;
  349. m_bIn3DPaintMode = false;
  350. m_bDrawingIn3DWorld = false;
  351. m_PlaySoundFunc = NULL;
  352. // Input system
  353. EnableWindowsMessages( true );
  354. // Initialize cursors
  355. InitCursors();
  356. // fonts initialization
  357. char language[64];
  358. bool bValid = false;
  359. if ( IsPC() )
  360. {
  361. memset( language, 0, sizeof( language ) );
  362. if ( CommandLine()->CheckParm( "-language" ) )
  363. {
  364. Q_strncpy( language, CommandLine()->ParmValue( "-language", "english"), sizeof( language ) );
  365. bValid = true;
  366. }
  367. else
  368. {
  369. #ifdef PLATFORM_WINDOWS
  370. bValid = system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", language, sizeof(language)-1 );
  371. #elif defined(OSX)
  372. static ConVarRef cl_language("cl_language");
  373. Q_strncpy( language, cl_language.GetString(), sizeof( language ) );
  374. bValid = true;
  375. #endif
  376. }
  377. }
  378. else
  379. {
  380. Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
  381. bValid = true;
  382. }
  383. if ( bValid )
  384. {
  385. FontManager().SetLanguage( language );
  386. }
  387. else
  388. {
  389. FontManager().SetLanguage( "english" );
  390. }
  391. #ifdef LINUX
  392. FontManager().SetFontDataHelper( &CMatSystemSurface::FontDataHelper );
  393. #endif
  394. // font manager needs the file system and material system for bitmap fonts
  395. FontManager().SetInterfaces( g_pFullFileSystem, g_pMaterialSystem );
  396. g_bSpewFocus = CommandLine()->FindParm( "-vguifocus" ) ? true : false;
  397. return INIT_OK;
  398. }
  399. #if defined( ENABLE_HTMLWINDOW )
  400. void CMatSystemSurface::PurgeHTMLWindows( void )
  401. {
  402. // we need to delete these BEFORE we close our window down, as the browser is using it
  403. // if this DOESN'T run then it will crash when we close the main window
  404. for ( int i=0; i<GetHTMLWindowCount(); i++ )
  405. {
  406. HtmlWindow * RESTRICT htmlwindow = GetHTMLWindow(i);
  407. AssertMsg1( htmlwindow , "Tried to delete NULL HTMLWindow %d in CMatSystemSurface::Shutdown. This is probably important.", i );
  408. delete htmlwindow;
  409. }
  410. _htmlWindows.Purge();
  411. }
  412. #endif
  413. //-----------------------------------------------------------------------------
  414. // Purpose:
  415. //-----------------------------------------------------------------------------
  416. void CMatSystemSurface::Shutdown( void )
  417. {
  418. for ( int i = m_FileTypeImages.First(); i != m_FileTypeImages.InvalidIndex(); i = m_FileTypeImages.Next( i ) )
  419. {
  420. delete m_FileTypeImages[ i ];
  421. }
  422. m_FileTypeImages.RemoveAll();
  423. // Release all textures
  424. TextureDictionary()->DestroyAllTextures();
  425. m_iBoundTexture = -1;
  426. // Release the standard materials
  427. m_pWhite.Shutdown();
  428. m_FullScreenBufferMaterial.Shutdown();
  429. m_FullScreenBufferMaterialIgnoreAlpha.Shutdown();
  430. m_FullScreenBuffer.Shutdown();
  431. #if defined( ENABLE_HTMLWINDOW )
  432. // we need to delete these BEFORE we close our window down, as the browser is using it
  433. // if this DOESN'T run then it will crash when we close the main window
  434. PurgeHTMLWindows();
  435. #endif
  436. m_Titles.Purge();
  437. m_PaintStateStack.Purge();
  438. #if defined( WIN32 ) && !defined( _X360 )
  439. HMODULE gdiModule = NULL;
  440. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  441. // On custom font format Windows takes care of cleaning up the font when the process quits.
  442. // 4/4/2011, mikesart: Except we seem to occasionally bsod in Windows' cleanup code.
  443. // Googling for vCleanupPrivateFonts and left4dead results in several hits, and I'm hitting
  444. // it several times a day during process exit on my Win7 x64 machine. After talking to a
  445. // developer in GDI at Microsoft, this sounds like a race condition bug that was fixed in Windows 7 SP1.
  446. // and this workaround would fix the bug on !Win7 SP1 machines. Repro for me was to run
  447. // rendersystemtest.exe multiple times in a row.
  448. for (int i = 0; i < m_CustomFontHandles.Count(); i++)
  449. {
  450. ::RemoveFontMemResourceEx( m_CustomFontHandles[i] );
  451. }
  452. m_CustomFontHandles.RemoveAll();
  453. #else
  454. // release any custom font files
  455. // use newer function if possible
  456. gdiModule = ::LoadLibrary( "gdi32.dll" );
  457. typedef int (WINAPI *RemoveFontResourceExProc)(LPCTSTR, DWORD, PVOID);
  458. RemoveFontResourceExProc pRemoveFontResourceEx = NULL;
  459. if ( gdiModule )
  460. {
  461. pRemoveFontResourceEx = (RemoveFontResourceExProc)::GetProcAddress(gdiModule, "RemoveFontResourceExA");
  462. }
  463. for (int i = 0; i < m_CustomFontFileNames.Count(); i++)
  464. {
  465. if (pRemoveFontResourceEx)
  466. {
  467. // dvs: Keep removing the font until we get an error back. After consulting with Microsoft, it appears
  468. // that RemoveFontResourceEx must sometimes be called multiple times to work. Doing this insures that
  469. // when we load the font next time we get the real font instead of Ariel.
  470. int nRetries = 0;
  471. while ( (*pRemoveFontResourceEx)(m_CustomFontFileNames[i].String(), 0x10, NULL) && ( nRetries < 10 ) )
  472. {
  473. nRetries++;
  474. Msg( "Removed font resource %s on attempt %d.\n", m_CustomFontFileNames[i].String(), nRetries );
  475. }
  476. }
  477. else
  478. {
  479. // dvs: Keep removing the font until we get an error back. After consulting with Microsoft, it appears
  480. // that RemoveFontResourceEx must sometimes be called multiple times to work. Doing this insures that
  481. // when we load the font next time we get the real font instead of Ariel.
  482. int nRetries = 0;
  483. while ( ::RemoveFontResource(m_CustomFontFileNames[i].String()) && ( nRetries < 10 ) )
  484. {
  485. nRetries++;
  486. Msg( "Removed font resource %s on attempt %d.\n", m_CustomFontFileNames[i].String(), nRetries );
  487. }
  488. }
  489. }
  490. #endif // SUPPORT_CUSTOM_FONT_FORMAT
  491. #endif
  492. m_CustomFontFileNames.RemoveAll();
  493. m_BitmapFontFileNames.RemoveAll();
  494. m_BitmapFontFileMapping.RemoveAll();
  495. Cursor_ClearUserCursors();
  496. #if defined( WIN32 ) && !defined( _X360 )
  497. if ( gdiModule )
  498. {
  499. ::FreeLibrary(gdiModule);
  500. }
  501. #endif
  502. g_pLocalize->SetTextQuery( NULL );
  503. BaseClass::Shutdown();
  504. }
  505. void CMatSystemSurface::SetEmbeddedPanel(VPANEL pEmbeddedPanel)
  506. {
  507. m_pEmbeddedPanel = pEmbeddedPanel;
  508. ((VPanel *)pEmbeddedPanel)->Client()->RequestFocus(0);
  509. }
  510. //-----------------------------------------------------------------------------
  511. // hierarchy root
  512. //-----------------------------------------------------------------------------
  513. VPANEL CMatSystemSurface::GetEmbeddedPanel()
  514. {
  515. return m_pEmbeddedPanel;
  516. }
  517. void CMatSystemSurface::SetInputContext( InputContextHandle_t hContext )
  518. {
  519. m_hInputContext = hContext;
  520. if ( m_hInputContext != INPUT_CONTEXT_HANDLE_INVALID )
  521. {
  522. g_pInputStackSystem->EnableInputContext( m_hInputContext, m_bNeedsMouse );
  523. }
  524. }
  525. //-----------------------------------------------------------------------------
  526. // Purpose: cap bits
  527. // Warning: if you change this, make sure the SurfaceV28 wrapper above reports
  528. // the correct capabilities.
  529. //-----------------------------------------------------------------------------
  530. bool CMatSystemSurface::SupportsFontFeature( FontFeature_t feature )
  531. {
  532. switch (feature)
  533. {
  534. case FONT_FEATURE_ANTIALIASED_FONTS:
  535. case FONT_FEATURE_DROPSHADOW_FONTS:
  536. return true;
  537. case FONT_FEATURE_OUTLINE_FONTS:
  538. if ( IsX360() )
  539. return false;
  540. return true;
  541. default:
  542. return false;
  543. };
  544. }
  545. //-----------------------------------------------------------------------------
  546. // Purpose: cap bits
  547. // Warning: if you change this, make sure the SurfaceV28 wrapper above reports
  548. // the correct capabilities.
  549. //-----------------------------------------------------------------------------
  550. bool CMatSystemSurface::SupportsFeature( SurfaceFeature_t feature )
  551. {
  552. switch (feature)
  553. {
  554. case ISurface::ESCAPE_KEY:
  555. return true;
  556. case ISurface::ANTIALIASED_FONTS:
  557. case ISurface::DROPSHADOW_FONTS:
  558. case ISurface::OUTLINE_FONTS:
  559. return SupportsFontFeature( ( FontFeature_t )feature );
  560. case ISurface::OPENING_NEW_HTML_WINDOWS:
  561. case ISurface::FRAME_MINIMIZE_MAXIMIZE:
  562. default:
  563. return false;
  564. };
  565. }
  566. //-----------------------------------------------------------------------------
  567. // Hook needed to Get input to work
  568. //-----------------------------------------------------------------------------
  569. void CMatSystemSurface::SetAppDrivesInput( bool bLetAppDriveInput )
  570. {
  571. m_bAppDrivesInput = bLetAppDriveInput;
  572. }
  573. bool CMatSystemSurface::HandleInputEvent( const InputEvent_t &event )
  574. {
  575. if ( !m_bEnableInput )
  576. return false;
  577. if ( !m_bAppDrivesInput )
  578. {
  579. g_pIInput->UpdateButtonState( event );
  580. }
  581. return InputHandleInputEvent( GetInputContext(), event );
  582. }
  583. //-----------------------------------------------------------------------------
  584. // Draws a panel in 3D space. Assumes view + projection are already set up
  585. // Also assumes the (x,y) coordinates of the panels are defined in 640xN coords
  586. // (N isn't necessary 480 because the panel may not be 4x3)
  587. // The width + height specified are the size of the panel in world coordinates
  588. //-----------------------------------------------------------------------------
  589. void CMatSystemSurface::DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int pw, int ph, float sw, float sh )
  590. {
  591. Assert( pRootPanel );
  592. // FIXME: When should such panels be solved?!?
  593. SolveTraverse( pRootPanel, false );
  594. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  595. // Force Z buffering to be on for all panels drawn...
  596. pRenderContext->OverrideDepthEnable( true, false );
  597. Assert(!m_bDrawingIn3DWorld);
  598. m_bDrawingIn3DWorld = true;
  599. StartDrawingIn3DSpace( panelCenterToWorld, pw, ph, sw, sh );
  600. ((VPanel *)pRootPanel)->Client()->Repaint();
  601. ((VPanel *)pRootPanel)->Client()->PaintTraverse(true, false);
  602. FinishDrawing();
  603. // Reset z buffering to normal state
  604. pRenderContext->OverrideDepthEnable( false, true );
  605. m_bDrawingIn3DWorld = false;
  606. }
  607. //-----------------------------------------------------------------------------
  608. // Purpose: Setup rendering for vgui on a panel existing in 3D space
  609. //-----------------------------------------------------------------------------
  610. void CMatSystemSurface::StartDrawingIn3DSpace( const VMatrix &screenToWorld, int pw, int ph, float sw, float sh )
  611. {
  612. g_bInDrawing = true;
  613. m_iBoundTexture = -1;
  614. int px = 0;
  615. int py = 0;
  616. m_pSurfaceExtents[0] = px;
  617. m_pSurfaceExtents[1] = py;
  618. m_pSurfaceExtents[2] = px + pw;
  619. m_pSurfaceExtents[3] = py + ph;
  620. // In order for this to work, the model matrix must have its origin
  621. // at the upper left corner of the screen. We must also scale down the
  622. // rendering from pixel space to screen space. Let's construct a matrix
  623. // transforming from pixel coordinates (640xN) to screen coordinates
  624. // (wxh, with the origin at the upper left of the screen). Then we'll
  625. // concatenate it with the panelCenterToWorld to produce pixelToWorld transform
  626. VMatrix pixelToScreen;
  627. // First, scale it so that 0->pw transforms to 0->sw
  628. MatrixBuildScale( pixelToScreen, sw / pw, -sh / ph, 1.0f );
  629. // Construct pixelToWorld
  630. VMatrix pixelToWorld;
  631. MatrixMultiply( screenToWorld, pixelToScreen, pixelToWorld );
  632. // make sure there is no translation and rotation laying around
  633. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  634. pRenderContext->MatrixMode( MATERIAL_MODEL );
  635. pRenderContext->PushMatrix();
  636. pRenderContext->LoadMatrix( pixelToWorld );
  637. // These are only here so that FinishDrawing works...
  638. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  639. pRenderContext->PushMatrix();
  640. pRenderContext->MatrixMode( MATERIAL_VIEW );
  641. pRenderContext->PushMatrix();
  642. // Always enable scissoring (translate to origin because of the glTranslatef call above..)
  643. EnableScissor( true );
  644. m_nTranslateX = 0;
  645. m_nTranslateY = 0;
  646. m_flAlphaMultiplier = 1.0f;
  647. }
  648. //-----------------------------------------------------------------------------
  649. // Purpose: Setup ortho for vgui
  650. //-----------------------------------------------------------------------------
  651. // we may need to offset by 0.5 texels to account for the different in pixel vs. texel centers in dx7-9
  652. // however, we do this fixup already when we set up the texture coordinates for all materials/fonts
  653. // so in theory we shouldn't need to do any adjustments for setting up the screen
  654. // HOWEVER, we must do the offset, else the driver will think the text is something that should
  655. // be antialiased, so the text will look broken if antialiasing is turned on (usually forced on in the driver)
  656. // TOGL Linux/Win now automatically accounts for the half pixel offset between D3D9 vs. GL, if we are using the old OSX togl lib then we need pixel offsets to be 0.0f
  657. float g_flPixelOffsetX = 0.5f;
  658. float g_flPixelOffsetY = 0.5f;
  659. bool g_bCheckedCommandLine = false;
  660. extern void ___stop___( void );
  661. void CMatSystemSurface::StartDrawing( void )
  662. {
  663. MAT_FUNC;
  664. if ( !g_bCheckedCommandLine )
  665. {
  666. g_bCheckedCommandLine = true;
  667. const char *pX = CommandLine()->ParmValue( "-pixel_offset_x", (const char*)NULL );
  668. if ( pX )
  669. g_flPixelOffsetX = atof( pX );
  670. const char *pY = CommandLine()->ParmValue( "-pixel_offset_y", (const char*)NULL );
  671. if ( pY )
  672. g_flPixelOffsetY = atof( pY );
  673. }
  674. g_bInDrawing = true;
  675. m_iBoundTexture = -1;
  676. int x, y, width, height;
  677. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  678. pRenderContext->GetViewport( x, y, width, height);
  679. m_pSurfaceExtents[0] = x;
  680. m_pSurfaceExtents[1] = y;
  681. m_pSurfaceExtents[2] = x + width;
  682. m_pSurfaceExtents[3] = y + height;
  683. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  684. pRenderContext->PushMatrix();
  685. pRenderContext->LoadIdentity();
  686. pRenderContext->Scale( 1, -1, 1 );
  687. //___stop___();
  688. pRenderContext->Ortho( g_flPixelOffsetX, g_flPixelOffsetY, width + g_flPixelOffsetX, height + g_flPixelOffsetY, -1.0f, 1.0f );
  689. // make sure there is no translation and rotation laying around
  690. pRenderContext->MatrixMode( MATERIAL_MODEL );
  691. pRenderContext->PushMatrix();
  692. pRenderContext->LoadIdentity();
  693. // Always enable scissoring (translate to origin because of the glTranslatef call above..)
  694. EnableScissor( true );
  695. m_nTranslateX = 0;
  696. m_nTranslateY = 0;
  697. pRenderContext->MatrixMode( MATERIAL_VIEW );
  698. pRenderContext->PushMatrix();
  699. pRenderContext->LoadIdentity();
  700. }
  701. //-----------------------------------------------------------------------------
  702. // Purpose:
  703. //-----------------------------------------------------------------------------
  704. void CMatSystemSurface::FinishDrawing( void )
  705. {
  706. MAT_FUNC;
  707. // We're done with scissoring
  708. EnableScissor( false );
  709. // Restore the matrices
  710. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  711. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  712. pRenderContext->PopMatrix();
  713. pRenderContext->MatrixMode( MATERIAL_MODEL );
  714. pRenderContext->PopMatrix();
  715. pRenderContext->MatrixMode( MATERIAL_VIEW );
  716. pRenderContext->PopMatrix();
  717. Assert( g_bInDrawing );
  718. g_bInDrawing = false;
  719. }
  720. //-----------------------------------------------------------------------------
  721. // frame
  722. //-----------------------------------------------------------------------------
  723. void CMatSystemSurface::RunFrame()
  724. {
  725. #ifdef OSX
  726. void CursorRunFrame();
  727. CursorRunFrame();
  728. #endif
  729. int nPollCount = g_pInputSystem->GetPollCount();
  730. if ( m_nLastInputPollCount == nPollCount )
  731. return;
  732. // If this isn't true, we've lost input!
  733. if ( !m_bAppDrivesInput && ( m_nLastInputPollCount != nPollCount - 1 ) )
  734. {
  735. Assert( 0 );
  736. Warning( "Vgui is losing input messages! Call brian!\n" );
  737. }
  738. m_nLastInputPollCount = nPollCount;
  739. if ( m_bAppDrivesInput )
  740. return;
  741. // Generate all input messages
  742. int nEventCount = g_pInputSystem->GetEventCount();
  743. const InputEvent_t* pEvents = g_pInputSystem->GetEventData( );
  744. for ( int i = 0; i < nEventCount; ++i )
  745. {
  746. HandleInputEvent( pEvents[i] );
  747. }
  748. }
  749. //-----------------------------------------------------------------------------
  750. // Sets up a particular painting state...
  751. //-----------------------------------------------------------------------------
  752. void CMatSystemSurface::SetupPaintState( const PaintState_t &paintState )
  753. {
  754. m_nTranslateX = paintState.m_iTranslateX;
  755. m_nTranslateY = paintState.m_iTranslateY;
  756. SetScissorRect( paintState.m_iScissorLeft, paintState.m_iScissorTop,
  757. paintState.m_iScissorRight, paintState.m_iScissorBottom );
  758. }
  759. //-----------------------------------------------------------------------------
  760. // Indicates a particular panel is about to be rendered
  761. //-----------------------------------------------------------------------------
  762. void CMatSystemSurface::PushMakeCurrent(VPANEL pPanel, bool useInSets)
  763. {
  764. int inSets[4] = {0, 0, 0, 0};
  765. int absExtents[4];
  766. int clipRect[4];
  767. if (useInSets)
  768. {
  769. g_pVGuiPanel->GetInset(pPanel, inSets[0], inSets[1], inSets[2], inSets[3]);
  770. }
  771. g_pVGuiPanel->GetAbsPos(pPanel, absExtents[0], absExtents[1]);
  772. int wide, tall;
  773. g_pVGuiPanel->GetSize(pPanel, wide, tall);
  774. absExtents[2] = absExtents[0] + wide;
  775. absExtents[3] = absExtents[1] + tall;
  776. g_pVGuiPanel->GetClipRect(pPanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3]);
  777. int i = m_PaintStateStack.AddToTail();
  778. PaintState_t &paintState = m_PaintStateStack[i];
  779. paintState.m_pPanel = pPanel;
  780. // Determine corrected top left origin
  781. paintState.m_iTranslateX = inSets[0] + absExtents[0] - m_pSurfaceExtents[0];
  782. paintState.m_iTranslateY = inSets[1] + absExtents[1] - m_pSurfaceExtents[1];
  783. // Setup clipping rectangle for scissoring
  784. paintState.m_iScissorLeft = clipRect[0] - m_pSurfaceExtents[0];
  785. paintState.m_iScissorTop = clipRect[1] - m_pSurfaceExtents[1];
  786. paintState.m_iScissorRight = clipRect[2] - m_pSurfaceExtents[0];
  787. paintState.m_iScissorBottom = clipRect[3] - m_pSurfaceExtents[1];
  788. SetupPaintState( paintState );
  789. }
  790. void CMatSystemSurface::PopMakeCurrent(VPANEL pPanel)
  791. {
  792. // draw any remaining text
  793. if ( m_nBatchedCharVertCount > 0 )
  794. {
  795. DrawFlushText();
  796. }
  797. int top = m_PaintStateStack.Count() - 1;
  798. // More pops that pushes?
  799. Assert( top >= 0 );
  800. // Didn't pop in reverse order of push?
  801. Assert( m_PaintStateStack[top].m_pPanel == pPanel );
  802. m_PaintStateStack.Remove(top);
  803. if (top > 0)
  804. SetupPaintState( m_PaintStateStack[top-1] );
  805. // m_iBoundTexture = -1;
  806. }
  807. //-----------------------------------------------------------------------------
  808. // Color Setting methods
  809. //-----------------------------------------------------------------------------
  810. void CMatSystemSurface::DrawSetColor(int r, int g, int b, int a)
  811. {
  812. Assert( g_bInDrawing );
  813. m_DrawColor[0]=(unsigned char)r;
  814. m_DrawColor[1]=(unsigned char)g;
  815. m_DrawColor[2]=(unsigned char)b;
  816. m_DrawColor[3]=(unsigned char)(a * m_flAlphaMultiplier);
  817. }
  818. void CMatSystemSurface::DrawSetColor(Color col)
  819. {
  820. Assert( g_bInDrawing );
  821. DrawSetColor(col[0], col[1], col[2], col[3]);
  822. }
  823. //-----------------------------------------------------------------------------
  824. // nVidia Stereoscopic Support methods
  825. //-----------------------------------------------------------------------------
  826. void CMatSystemSurface::DrawSetApparentDepth( float flDepth )
  827. {
  828. Assert( g_bInDrawing );
  829. if ( !materials->IsStereoSupported() )
  830. {
  831. return;
  832. }
  833. // Can only skip the DrawFlushText because we'll expect to pop the stack in a bit and we need to have pushed. Otherwise we'd
  834. // have to have a separate stack for whether we pushed here, which would be ugly.
  835. if ( flDepth != m_flApparentDepth )
  836. {
  837. // Have to flush text, otherwise it's drawn incorrectly.
  838. DrawFlushText();
  839. }
  840. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  841. if ( flDepth <= STEREO_INVALID )
  842. {
  843. flDepth = STEREO_NOOP;
  844. }
  845. // Scaling by all four coordinates will cause stereo objects to be drawn at the depth specified
  846. // but will not otherwise affect the location of the object because of the eventual perspective divide.
  847. VMatrix depthMatrix( flDepth, 0, 0, 0,
  848. 0, flDepth, 0, 0,
  849. 0, 0, flDepth, 0,
  850. 0, 0, 0, flDepth );
  851. pRenderContext->MatrixMode( MATERIAL_VIEW );
  852. pRenderContext->PushMatrix();
  853. pRenderContext->LoadMatrix( depthMatrix );
  854. m_flApparentDepth = flDepth;
  855. }
  856. void CMatSystemSurface::DrawClearApparentDepth()
  857. {
  858. if ( !materials->IsStereoSupported() )
  859. {
  860. return;
  861. }
  862. // Have to flush text, otherwise it's drawn incorrectly.
  863. DrawFlushText();
  864. m_flApparentDepth = STEREO_NOOP;
  865. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  866. pRenderContext->MatrixMode( MATERIAL_VIEW );
  867. pRenderContext->PopMatrix();
  868. }
  869. //-----------------------------------------------------------------------------
  870. // material Setting methods
  871. //-----------------------------------------------------------------------------
  872. void CMatSystemSurface::InternalSetMaterial( IMaterial *pMaterial )
  873. {
  874. if (!pMaterial)
  875. {
  876. pMaterial = m_pWhite;
  877. }
  878. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  879. m_pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  880. }
  881. //-----------------------------------------------------------------------------
  882. // Helper method to initialize vertices (transforms them into screen space too)
  883. //-----------------------------------------------------------------------------
  884. void CMatSystemSurface::InitVertex( Vertex_t &vertex, int x, int y, float u, float v )
  885. {
  886. vertex.m_Position.Init( x + m_nTranslateX, y + m_nTranslateY );
  887. vertex.m_TexCoord.Init( u, v );
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Draws a line!
  891. //-----------------------------------------------------------------------------
  892. void CMatSystemSurface::DrawTexturedLineInternal( const Vertex_t &a, const Vertex_t &b )
  893. {
  894. MAT_FUNC;
  895. Assert( !m_bIn3DPaintMode );
  896. // Don't bother drawing fully transparent lines
  897. if( m_DrawColor[3] == 0 )
  898. return;
  899. Vertex_t verts[2] = { a, b };
  900. verts[0].m_Position.x += m_nTranslateX + g_flPixelOffsetX;
  901. verts[0].m_Position.y += m_nTranslateY + g_flPixelOffsetY;
  902. verts[1].m_Position.x += m_nTranslateX + g_flPixelOffsetX;
  903. verts[1].m_Position.y += m_nTranslateY + g_flPixelOffsetY;
  904. Vertex_t clippedVerts[2];
  905. if (!ClipLine( verts, clippedVerts ))
  906. return;
  907. meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 1 );
  908. meshBuilder.Position3f( clippedVerts[0].m_Position.x, clippedVerts[0].m_Position.y, m_flZPos );
  909. meshBuilder.Color4ubv( m_DrawColor );
  910. meshBuilder.TexCoord2fv( 0, clippedVerts[0].m_TexCoord.Base() );
  911. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  912. meshBuilder.Position3f( clippedVerts[1].m_Position.x, clippedVerts[1].m_Position.y, m_flZPos );
  913. meshBuilder.Color4ubv( m_DrawColor );
  914. meshBuilder.TexCoord2fv( 0, clippedVerts[1].m_TexCoord.Base() );
  915. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  916. meshBuilder.End();
  917. m_pMesh->Draw();
  918. }
  919. void CMatSystemSurface::DrawLine( int x0, int y0, int x1, int y1 )
  920. {
  921. MAT_FUNC;
  922. Assert( g_bInDrawing );
  923. // Don't bother drawing fully transparent lines
  924. if( m_DrawColor[3] == 0 )
  925. return;
  926. Vertex_t verts[2];
  927. verts[0].Init( Vector2D( x0, y0 ), Vector2D( 0, 0 ) );
  928. verts[1].Init( Vector2D( x1, y1 ), Vector2D( 1, 1 ) );
  929. InternalSetMaterial( );
  930. DrawTexturedLineInternal( verts[0], verts[1] );
  931. }
  932. void CMatSystemSurface::DrawTexturedLine( const Vertex_t &a, const Vertex_t &b )
  933. {
  934. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  935. InternalSetMaterial( pMaterial );
  936. DrawTexturedLineInternal( a, b );
  937. }
  938. //-----------------------------------------------------------------------------
  939. // Draws a line!
  940. //-----------------------------------------------------------------------------
  941. void CMatSystemSurface::DrawPolyLine( int *px, int *py ,int n )
  942. {
  943. MAT_FUNC;
  944. Assert( g_bInDrawing );
  945. Assert( !m_bIn3DPaintMode );
  946. // Don't bother drawing fully transparent lines
  947. if( m_DrawColor[3] == 0 )
  948. return;
  949. InternalSetMaterial( );
  950. meshBuilder.Begin( m_pMesh, MATERIAL_LINES, n );
  951. for ( int i = 0; i < n ; i++ )
  952. {
  953. int inext = ( i + 1 ) % n;
  954. Vertex_t verts[2];
  955. Vertex_t clippedVerts[2];
  956. int x0, y0, x1, y1;
  957. x0 = px[ i ];
  958. x1 = px[ inext ];
  959. y0 = py[ i ];
  960. y1 = py[ inext ];
  961. InitVertex( verts[0], x0, y0, 0, 0 );
  962. InitVertex( verts[1], x1, y1, 1, 1 );
  963. if (!ClipLine( verts, clippedVerts ))
  964. continue;
  965. meshBuilder.Position3f( clippedVerts[0].m_Position.x+ g_flPixelOffsetX, clippedVerts[0].m_Position.y + g_flPixelOffsetY, m_flZPos );
  966. meshBuilder.Color4ubv( m_DrawColor );
  967. meshBuilder.TexCoord2fv( 0, clippedVerts[0].m_TexCoord.Base() );
  968. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  969. meshBuilder.Position3f( clippedVerts[1].m_Position.x+ g_flPixelOffsetX, clippedVerts[1].m_Position.y + g_flPixelOffsetY, m_flZPos );
  970. meshBuilder.Color4ubv( m_DrawColor );
  971. meshBuilder.TexCoord2fv( 0, clippedVerts[1].m_TexCoord.Base() );
  972. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  973. }
  974. meshBuilder.End();
  975. m_pMesh->Draw();
  976. }
  977. void CMatSystemSurface::DrawTexturedPolyLine( const Vertex_t *p,int n )
  978. {
  979. int iPrev = n - 1;
  980. for ( int i=0; i < n; i++ )
  981. {
  982. DrawTexturedLine( p[iPrev], p[i] );
  983. iPrev = i;
  984. }
  985. }
  986. //-----------------------------------------------------------------------------
  987. // Draws a quad:
  988. //-----------------------------------------------------------------------------
  989. void CMatSystemSurface::DrawQuad( const Vertex_t &ul, const Vertex_t &lr, unsigned char *pColor )
  990. {
  991. Assert( !m_bIn3DPaintMode );
  992. if ( !m_pMesh )
  993. return;
  994. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
  995. meshBuilder.Position3f( ul.m_Position.x, ul.m_Position.y, m_flZPos );
  996. meshBuilder.Color4ubv( pColor );
  997. meshBuilder.TexCoord2f( 0, ul.m_TexCoord.x, ul.m_TexCoord.y );
  998. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  999. meshBuilder.Position3f( lr.m_Position.x, ul.m_Position.y, m_flZPos );
  1000. meshBuilder.Color4ubv( pColor );
  1001. meshBuilder.TexCoord2f( 0, lr.m_TexCoord.x, ul.m_TexCoord.y );
  1002. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1003. meshBuilder.Position3f( lr.m_Position.x, lr.m_Position.y, m_flZPos );
  1004. meshBuilder.Color4ubv( pColor );
  1005. meshBuilder.TexCoord2f( 0, lr.m_TexCoord.x, lr.m_TexCoord.y );
  1006. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1007. meshBuilder.Position3f( ul.m_Position.x, lr.m_Position.y, m_flZPos );
  1008. meshBuilder.Color4ubv( pColor );
  1009. meshBuilder.TexCoord2f( 0, ul.m_TexCoord.x, lr.m_TexCoord.y );
  1010. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1011. meshBuilder.End();
  1012. m_pMesh->Draw();
  1013. }
  1014. //-----------------------------------------------------------------------------
  1015. // Purpose: Draws an array of quads
  1016. //-----------------------------------------------------------------------------
  1017. void CMatSystemSurface::DrawQuadArray( int quadCount, Vertex_t *pVerts, unsigned char *pColor, bool bShouldClip )
  1018. {
  1019. Assert( !m_bIn3DPaintMode );
  1020. if ( !m_pMesh )
  1021. return;
  1022. vgui::Vertex_t ulc;
  1023. vgui::Vertex_t lrc;
  1024. vgui::Vertex_t *pulc;
  1025. vgui::Vertex_t *plrc;
  1026. int nMaxVertices, nMaxIndices;
  1027. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1028. pRenderContext->GetMaxToRender( m_pMesh, false, &nMaxVertices, &nMaxIndices );
  1029. if ( !nMaxVertices || !nMaxIndices )
  1030. return; // probably in alt-tab
  1031. int nMaxQuads = nMaxVertices / 4;
  1032. nMaxQuads = MIN( nMaxQuads, nMaxIndices / 6 );
  1033. int nFirstQuad = 0;
  1034. int nQuadsRemaining = quadCount;
  1035. while ( nQuadsRemaining > 0 )
  1036. {
  1037. quadCount = MIN( nQuadsRemaining, nMaxQuads );
  1038. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, quadCount );
  1039. if ( bShouldClip )
  1040. {
  1041. for ( int q = 0; q < quadCount; ++q )
  1042. {
  1043. int i = q + nFirstQuad;
  1044. PREFETCH360( &pVerts[ 2 * ( i + 1 ) ], 0 );
  1045. if ( !ClipRect( pVerts[2*i], pVerts[2*i + 1], &ulc, &lrc ) )
  1046. {
  1047. continue;
  1048. }
  1049. pulc = &ulc;
  1050. plrc = &lrc;
  1051. meshBuilder.Position3f( pulc->m_Position.x, pulc->m_Position.y, m_flZPos );
  1052. meshBuilder.Color4ubv( pColor );
  1053. meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, pulc->m_TexCoord.y );
  1054. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1055. meshBuilder.Position3f( plrc->m_Position.x, pulc->m_Position.y, m_flZPos );
  1056. meshBuilder.Color4ubv( pColor );
  1057. meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, pulc->m_TexCoord.y );
  1058. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1059. meshBuilder.Position3f( plrc->m_Position.x, plrc->m_Position.y, m_flZPos );
  1060. meshBuilder.Color4ubv( pColor );
  1061. meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, plrc->m_TexCoord.y );
  1062. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1063. meshBuilder.Position3f( pulc->m_Position.x, plrc->m_Position.y, m_flZPos );
  1064. meshBuilder.Color4ubv( pColor );
  1065. meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, plrc->m_TexCoord.y );
  1066. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1067. }
  1068. }
  1069. else
  1070. {
  1071. for ( int q = 0; q < quadCount; ++q )
  1072. {
  1073. int i = q + nFirstQuad;
  1074. PREFETCH360( &pVerts[ 2 * ( i + 1 ) ], 0 );
  1075. pulc = &pVerts[2*i];
  1076. plrc = &pVerts[2*i + 1];
  1077. meshBuilder.Position3f( pulc->m_Position.x, pulc->m_Position.y, m_flZPos );
  1078. meshBuilder.Color4ubv( pColor );
  1079. meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, pulc->m_TexCoord.y );
  1080. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1081. meshBuilder.Position3f( plrc->m_Position.x, pulc->m_Position.y, m_flZPos );
  1082. meshBuilder.Color4ubv( pColor );
  1083. meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, pulc->m_TexCoord.y );
  1084. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1085. meshBuilder.Position3f( plrc->m_Position.x, plrc->m_Position.y, m_flZPos );
  1086. meshBuilder.Color4ubv( pColor );
  1087. meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, plrc->m_TexCoord.y );
  1088. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1089. meshBuilder.Position3f( pulc->m_Position.x, plrc->m_Position.y, m_flZPos );
  1090. meshBuilder.Color4ubv( pColor );
  1091. meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, plrc->m_TexCoord.y );
  1092. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1093. }
  1094. }
  1095. meshBuilder.End();
  1096. m_pMesh->Draw();
  1097. nFirstQuad += quadCount;
  1098. nQuadsRemaining -= quadCount;
  1099. }
  1100. }
  1101. //-----------------------------------------------------------------------------
  1102. // Purpose: Draws a rectangle colored with the current drawcolor
  1103. // using the white material
  1104. //-----------------------------------------------------------------------------
  1105. void CMatSystemSurface::DrawFilledRect( int x0, int y0, int x1, int y1 )
  1106. {
  1107. MAT_FUNC;
  1108. CMatRenderContextPtr prc( g_pMaterialSystem );
  1109. Assert( g_bInDrawing );
  1110. // Don't even bother drawing fully transparent junk
  1111. if( m_DrawColor[3]==0 )
  1112. return;
  1113. Vertex_t rect[2];
  1114. Vertex_t clippedRect[2];
  1115. InitVertex( rect[0], x0, y0, 0, 0 );
  1116. InitVertex( rect[1], x1, y1, 0, 0 );
  1117. // Fully clipped?
  1118. if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
  1119. return;
  1120. InternalSetMaterial();
  1121. DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
  1122. }
  1123. //-----------------------------------------------------------------------------
  1124. // Purpose: Draws an array of rectangles colored with the current drawcolor
  1125. // using the white material
  1126. //-----------------------------------------------------------------------------
  1127. void CMatSystemSurface::DrawFilledRectArray( IntRect *pRects, int numRects )
  1128. {
  1129. MAT_FUNC;
  1130. Assert( g_bInDrawing );
  1131. // Don't even bother drawing fully transparent junk
  1132. if( m_DrawColor[3]==0 )
  1133. return;
  1134. if ( !m_pMesh )
  1135. return;
  1136. InternalSetMaterial( );
  1137. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, numRects );
  1138. for (int i = 0; i < numRects; ++i )
  1139. {
  1140. Vertex_t rect[2];
  1141. Vertex_t clippedRect[2];
  1142. InitVertex( rect[0], pRects[i].x0, pRects[i].y0, 0, 0 );
  1143. InitVertex( rect[1], pRects[i].x1, pRects[i].y1, 0, 0 );
  1144. ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] );
  1145. Vertex_t &ul = clippedRect[0];
  1146. Vertex_t &lr = clippedRect[1];
  1147. meshBuilder.Position3f( ul.m_Position.x, ul.m_Position.y, m_flZPos );
  1148. meshBuilder.Color4ubv( m_DrawColor );
  1149. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
  1150. meshBuilder.Position3f( lr.m_Position.x, ul.m_Position.y, m_flZPos );
  1151. meshBuilder.Color4ubv( m_DrawColor );
  1152. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
  1153. meshBuilder.Position3f( lr.m_Position.x, lr.m_Position.y, m_flZPos );
  1154. meshBuilder.Color4ubv( m_DrawColor );
  1155. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
  1156. meshBuilder.Position3f( ul.m_Position.x, lr.m_Position.y, m_flZPos );
  1157. meshBuilder.Color4ubv( m_DrawColor );
  1158. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
  1159. }
  1160. meshBuilder.End();
  1161. m_pMesh->Draw();
  1162. }
  1163. //-----------------------------------------------------------------------------
  1164. // Draws a fade between the fadeStartPt and fadeEndPT with the current draw color oriented according to argument
  1165. // Example: DrawFilledRectFastFade( 10, 10, 100, 20, 50, 60, 255, 128, true );
  1166. // -this will draw
  1167. // a solid rect (10,10,50,20) //alpha 255
  1168. // a solid rect (50,10,60,20) //alpha faded from 255 to 128
  1169. // a solid rect (60,10,100,20) //alpha 128
  1170. //-----------------------------------------------------------------------------
  1171. void CMatSystemSurface::DrawFilledRectFastFade( int x0, int y0, int x1, int y1, int fadeStartPt, int fadeEndPt, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
  1172. {
  1173. if( bHorizontal )
  1174. {
  1175. if( alpha0 )
  1176. {
  1177. DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha0 );
  1178. DrawFilledRect( x0, y0, fadeStartPt, y1 );
  1179. }
  1180. DrawFilledRectFade( fadeStartPt, y0, fadeEndPt, y1, alpha0, alpha1, true );
  1181. if( alpha1 )
  1182. {
  1183. DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha1 );
  1184. DrawFilledRect( fadeEndPt, y0, x1, y1 );
  1185. }
  1186. }
  1187. else
  1188. {
  1189. if( alpha0 )
  1190. {
  1191. DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha0 );
  1192. DrawFilledRect( x0, y0, x1, fadeStartPt );
  1193. }
  1194. DrawFilledRectFade( x0, fadeStartPt, x1, fadeEndPt, alpha0, alpha1, false );
  1195. if( alpha1 )
  1196. {
  1197. DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha1 );
  1198. DrawFilledRect( x0, fadeEndPt, x1, y1 );
  1199. }
  1200. }
  1201. }
  1202. //-----------------------------------------------------------------------------
  1203. // Draws a fade with the current draw color oriented according to argument
  1204. //-----------------------------------------------------------------------------
  1205. void CMatSystemSurface::DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
  1206. {
  1207. MAT_FUNC;
  1208. Assert( g_bInDrawing );
  1209. // Scale the desired alphas by the surface alpha
  1210. float alphaScale = m_DrawColor[3] / 255.f;
  1211. alpha0 *= alphaScale;
  1212. alpha1 *= alphaScale;
  1213. // Don't even bother drawing fully transparent junk
  1214. if ( alpha0 == 0 && alpha1 == 0 )
  1215. return;
  1216. Vertex_t rect[2];
  1217. Vertex_t clippedRect[2];
  1218. InitVertex( rect[0], x0, y0, 0, 0 );
  1219. InitVertex( rect[1], x1, y1, 0, 0 );
  1220. // Fully clipped?
  1221. if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
  1222. return;
  1223. InternalSetMaterial();
  1224. unsigned char colors[4][4] = {0};
  1225. for ( int i=0; i<4; i++ )
  1226. {
  1227. // copy the rgb and leave the alpha at zero
  1228. Q_memcpy( colors[i], m_DrawColor, 3 );
  1229. }
  1230. unsigned char nAlpha0 = (alpha0 & 0xFF);
  1231. unsigned char nAlpha1 = (alpha1 & 0xFF);
  1232. if ( bHorizontal )
  1233. {
  1234. // horizontal fade
  1235. colors[0][3] = nAlpha0;
  1236. colors[1][3] = nAlpha1;
  1237. colors[2][3] = nAlpha1;
  1238. colors[3][3] = nAlpha0;
  1239. }
  1240. else
  1241. {
  1242. // vertical fade
  1243. colors[0][3] = nAlpha0;
  1244. colors[1][3] = nAlpha0;
  1245. colors[2][3] = nAlpha1;
  1246. colors[3][3] = nAlpha1;
  1247. }
  1248. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
  1249. meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
  1250. meshBuilder.Color4ubv( colors[0] );
  1251. meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
  1252. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1253. meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
  1254. meshBuilder.Color4ubv( colors[1] );
  1255. meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
  1256. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1257. meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
  1258. meshBuilder.Color4ubv( colors[2] );
  1259. meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
  1260. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1261. meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
  1262. meshBuilder.Color4ubv( colors[3] );
  1263. meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
  1264. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1265. meshBuilder.End();
  1266. m_pMesh->Draw();
  1267. }
  1268. void CMatSystemSurface::DrawTexturedSubRectGradient( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1, Color colStart, Color colEnd, bool bHorizontal )
  1269. {
  1270. MAT_FUNC;
  1271. Assert( g_bInDrawing );
  1272. // Scale the desired alphas by the surface alpha
  1273. colStart[3] *= m_flAlphaMultiplier;
  1274. colEnd[3] *= m_flAlphaMultiplier;
  1275. // Don't even bother drawing fully transparent junk
  1276. if ( colStart.a() == 0 && colEnd.a() == 0 )
  1277. return;
  1278. float s0, t0, s1, t1;
  1279. TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
  1280. float ssize = s1 - s0;
  1281. float tsize = t1 - t0;
  1282. // Rescale tex values into range of s0 to s1 ,etc.
  1283. texs0 = s0 + texs0 * ( ssize );
  1284. texs1 = s0 + texs1 * ( ssize );
  1285. text0 = t0 + text0 * ( tsize );
  1286. text1 = t0 + text1 * ( tsize );
  1287. Vertex_t rect[2];
  1288. Vertex_t clippedRect[2];
  1289. InitVertex( rect[0], x0, y0, texs0, text0 );
  1290. InitVertex( rect[1], x1, y1, texs1, text1 );
  1291. // Fully clipped?
  1292. if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
  1293. return;
  1294. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  1295. InternalSetMaterial( pMaterial );
  1296. unsigned char colors[4][4];
  1297. if ( bHorizontal )
  1298. {
  1299. // horizontal fade
  1300. Q_memcpy( colors[0], &colStart[0], sizeof( colors[0] ) );
  1301. Q_memcpy( colors[3], &colStart[0], sizeof( colors[3] ) );
  1302. Q_memcpy( colors[1], &colEnd[0], sizeof( colors[1] ) );
  1303. Q_memcpy( colors[2], &colEnd[0], sizeof( colors[2] ) );
  1304. }
  1305. else
  1306. {
  1307. // vertical fade
  1308. Q_memcpy( colors[0], &colStart[0], sizeof( colors[0] ) );
  1309. Q_memcpy( colors[1], &colStart[0], sizeof( colors[1] ) );
  1310. Q_memcpy( colors[2], &colEnd[0], sizeof( colors[2] ) );
  1311. Q_memcpy( colors[3], &colEnd[0], sizeof( colors[3] ) );
  1312. }
  1313. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
  1314. meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
  1315. meshBuilder.Color4ubv( colors[0] );
  1316. meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
  1317. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1318. meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
  1319. meshBuilder.Color4ubv( colors[1] );
  1320. meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
  1321. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1322. meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
  1323. meshBuilder.Color4ubv( colors[2] );
  1324. meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
  1325. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1326. meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
  1327. meshBuilder.Color4ubv( colors[3] );
  1328. meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
  1329. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1330. meshBuilder.End();
  1331. m_pMesh->Draw();
  1332. }
  1333. //-----------------------------------------------------------------------------
  1334. // Purpose: Draws an unfilled rectangle in the current drawcolor
  1335. //-----------------------------------------------------------------------------
  1336. void CMatSystemSurface::DrawOutlinedRect(int x0,int y0,int x1,int y1)
  1337. {
  1338. MAT_FUNC;
  1339. // Don't even bother drawing fully transparent junk
  1340. if ( m_DrawColor[3] == 0 )
  1341. return;
  1342. DrawFilledRect(x0,y0,x1,y0+1); //top
  1343. DrawFilledRect(x0,y1-1,x1,y1); //bottom
  1344. DrawFilledRect(x0,y0+1,x0+1,y1-1); //left
  1345. DrawFilledRect(x1-1,y0+1,x1,y1-1); //right
  1346. }
  1347. //-----------------------------------------------------------------------------
  1348. // Purpose: Draws an outlined circle in the current drawcolor
  1349. //-----------------------------------------------------------------------------
  1350. void CMatSystemSurface::DrawOutlinedCircle(int x, int y, int radius, int segments)
  1351. {
  1352. MAT_FUNC;
  1353. Assert( g_bInDrawing );
  1354. Assert( !m_bIn3DPaintMode );
  1355. // Don't even bother drawing fully transparent junk
  1356. if( m_DrawColor[3]==0 )
  1357. return;
  1358. // NOTE: Gotta use lines instead of linelist or lineloop due to clipping
  1359. InternalSetMaterial( );
  1360. meshBuilder.Begin( m_pMesh, MATERIAL_LINES, segments );
  1361. Vertex_t renderVertex[2];
  1362. Vertex_t vertex[2];
  1363. vertex[0].m_Position.Init( m_nTranslateX + x + radius, m_nTranslateY + y );
  1364. vertex[0].m_TexCoord.Init( 1.0f, 0.5f );
  1365. float invDelta = 2.0f * M_PI / segments;
  1366. for ( int i = 1; i <= segments; ++i )
  1367. {
  1368. float flRadians = i * invDelta;
  1369. float ca = cos( flRadians );
  1370. float sa = sin( flRadians );
  1371. // Rotate it around the circle
  1372. vertex[1].m_Position.x = m_nTranslateX + x + (radius * ca);
  1373. vertex[1].m_Position.y = m_nTranslateY + y + (radius * sa);
  1374. vertex[1].m_TexCoord.x = 0.5f * (ca + 1.0f);
  1375. vertex[1].m_TexCoord.y = 0.5f * (sa + 1.0f);
  1376. if (ClipLine( vertex, renderVertex ))
  1377. {
  1378. meshBuilder.Position3f( renderVertex[0].m_Position.x, renderVertex[0].m_Position.y, m_flZPos );
  1379. meshBuilder.Color4ubv( m_DrawColor );
  1380. meshBuilder.TexCoord2fv( 0, renderVertex[0].m_TexCoord.Base() );
  1381. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1382. meshBuilder.Position3f( renderVertex[1].m_Position.x, renderVertex[1].m_Position.y, m_flZPos );
  1383. meshBuilder.Color4ubv( m_DrawColor );
  1384. meshBuilder.TexCoord2fv( 0, renderVertex[1].m_TexCoord.Base() );
  1385. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1386. }
  1387. vertex[0].m_Position = vertex[1].m_Position;
  1388. vertex[0].m_TexCoord = vertex[1].m_TexCoord;
  1389. }
  1390. meshBuilder.End();
  1391. m_pMesh->Draw();
  1392. }
  1393. //-----------------------------------------------------------------------------
  1394. // Loads a particular texture (material)
  1395. //-----------------------------------------------------------------------------
  1396. int CMatSystemSurface::CreateNewTextureID( bool procedural /*=false*/ )
  1397. {
  1398. return TextureDictionary()->CreateTexture( procedural );
  1399. }
  1400. void CMatSystemSurface::DestroyTextureID( int id )
  1401. {
  1402. TextureDictionary()->DestroyTexture( id );
  1403. }
  1404. bool CMatSystemSurface::DeleteTextureByID(int id)
  1405. {
  1406. TextureDictionary()->DestroyTexture( id );
  1407. return false;
  1408. }
  1409. //-----------------------------------------------------------------------------
  1410. // Purpose:
  1411. // Input : id -
  1412. // *filename -
  1413. // maxlen -
  1414. // Output : Returns true on success, false on failure.
  1415. //-----------------------------------------------------------------------------
  1416. bool CMatSystemSurface::DrawGetTextureFile(int id, char *filename, int maxlen )
  1417. {
  1418. if ( !TextureDictionary()->IsValidId( id ) )
  1419. return false;
  1420. IMaterial *texture = TextureDictionary()->GetTextureMaterial(id);
  1421. if ( !texture )
  1422. return false;
  1423. Q_strncpy( filename, texture->GetName(), maxlen );
  1424. return true;
  1425. }
  1426. //-----------------------------------------------------------------------------
  1427. // Purpose:
  1428. // Input : id - texture id
  1429. // Output : returns IMaterial for the referenced texture
  1430. //-----------------------------------------------------------------------------
  1431. IVguiMatInfo *CMatSystemSurface::DrawGetTextureMatInfoFactory(int id)
  1432. {
  1433. if ( !TextureDictionary()->IsValidId( id ) )
  1434. return NULL;
  1435. IMaterial *texture = TextureDictionary()->GetTextureMaterial(id);
  1436. if ( texture == NULL )
  1437. return NULL;
  1438. return new CVguiMatInfo(texture);
  1439. }
  1440. //-----------------------------------------------------------------------------
  1441. // Purpose:
  1442. // Input : *filename -
  1443. // Output : int
  1444. //-----------------------------------------------------------------------------
  1445. int CMatSystemSurface::DrawGetTextureId( char const *filename )
  1446. {
  1447. return TextureDictionary()->FindTextureIdForTextureFile( filename );
  1448. }
  1449. //-----------------------------------------------------------------------------
  1450. // Associates a texture with a material file (also binds it)
  1451. //-----------------------------------------------------------------------------
  1452. void CMatSystemSurface::DrawSetTextureFile(int id, const char *pFileName, int hardwareFilter, bool forceReload /*= false*/)
  1453. {
  1454. TextureDictionary()->BindTextureToFile( id, pFileName );
  1455. DrawSetTexture( id );
  1456. }
  1457. //-----------------------------------------------------------------------------
  1458. // Associates a texture with a material file (also binds it)
  1459. //-----------------------------------------------------------------------------
  1460. void CMatSystemSurface::DrawSetTextureMaterial(int id, IMaterial *pMaterial)
  1461. {
  1462. TextureDictionary()->BindTextureToMaterial( id, pMaterial );
  1463. DrawSetTexture( id );
  1464. }
  1465. IMaterial *CMatSystemSurface::DrawGetTextureMaterial( int id )
  1466. {
  1467. return TextureDictionary()->GetTextureMaterial( id );
  1468. }
  1469. void CMatSystemSurface::ReferenceProceduralMaterial( int id, int referenceId, IMaterial *pMaterial )
  1470. {
  1471. TextureDictionary()->BindTextureToMaterialReference( id, referenceId, pMaterial );
  1472. }
  1473. //-----------------------------------------------------------------------------
  1474. // Binds a texture
  1475. //-----------------------------------------------------------------------------
  1476. void CMatSystemSurface::DrawSetTexture( int id )
  1477. {
  1478. // if we're switching textures, flush any batched text
  1479. if ( id != m_iBoundTexture )
  1480. {
  1481. DrawFlushText();
  1482. m_iBoundTexture = id;
  1483. if ( id == -1 )
  1484. {
  1485. // ensure we unbind current material that may go away
  1486. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1487. pRenderContext->Bind( m_pWhite );
  1488. }
  1489. }
  1490. }
  1491. //-----------------------------------------------------------------------------
  1492. // Returns texture size
  1493. //-----------------------------------------------------------------------------
  1494. void CMatSystemSurface::DrawGetTextureSize(int id, int &iWide, int &iTall)
  1495. {
  1496. TextureDictionary()->GetTextureSize( id, iWide, iTall );
  1497. }
  1498. //-----------------------------------------------------------------------------
  1499. // Draws a textured rectangle
  1500. //-----------------------------------------------------------------------------
  1501. void CMatSystemSurface::DrawTexturedRect( int x0, int y0, int x1, int y1 )
  1502. {
  1503. MAT_FUNC;
  1504. Assert( g_bInDrawing );
  1505. // Don't even bother drawing fully transparent junk
  1506. if( m_DrawColor[3] == 0 )
  1507. return;
  1508. float s0, t0, s1, t1;
  1509. TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
  1510. Vertex_t rect[2];
  1511. Vertex_t clippedRect[2];
  1512. InitVertex( rect[0], x0, y0, s0, t0 );
  1513. InitVertex( rect[1], x1, y1, s1, t1 );
  1514. // Fully clipped?
  1515. if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
  1516. return;
  1517. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  1518. InternalSetMaterial( pMaterial );
  1519. DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
  1520. }
  1521. //-----------------------------------------------------------------------------
  1522. // Draws a textured rectangle
  1523. //-----------------------------------------------------------------------------
  1524. void CMatSystemSurface::DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 )
  1525. {
  1526. MAT_FUNC;
  1527. Assert( g_bInDrawing );
  1528. // Don't even bother drawing fully transparent junk
  1529. if( m_DrawColor[3] == 0 )
  1530. return;
  1531. float s0, t0, s1, t1;
  1532. TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
  1533. float ssize = s1 - s0;
  1534. float tsize = t1 - t0;
  1535. // Rescale tex values into range of s0 to s1 ,etc.
  1536. texs0 = s0 + texs0 * ( ssize );
  1537. texs1 = s0 + texs1 * ( ssize );
  1538. text0 = t0 + text0 * ( tsize );
  1539. text1 = t0 + text1 * ( tsize );
  1540. Vertex_t rect[2];
  1541. Vertex_t clippedRect[2];
  1542. InitVertex( rect[0], x0, y0, texs0, text0 );
  1543. InitVertex( rect[1], x1, y1, texs1, text1 );
  1544. // Fully clipped?
  1545. if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
  1546. return;
  1547. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  1548. InternalSetMaterial( pMaterial );
  1549. DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
  1550. }
  1551. //-----------------------------------------------------------------------------
  1552. // Draws a textured polygon
  1553. //-----------------------------------------------------------------------------
  1554. void CMatSystemSurface::DrawTexturedPolygon(int n, Vertex_t *pVertices, bool bClipVertices /*= true*/ )
  1555. {
  1556. Assert( !m_bIn3DPaintMode );
  1557. Assert( g_bInDrawing );
  1558. // Don't even bother drawing fully transparent junk
  1559. if( (n == 0) || (m_DrawColor[3]==0) )
  1560. return;
  1561. if ( bClipVertices )
  1562. {
  1563. int iCount;
  1564. Vertex_t **ppClippedVerts = NULL;
  1565. iCount = ClipPolygon( n, pVertices, m_nTranslateX, m_nTranslateY, &ppClippedVerts );
  1566. if (iCount <= 0)
  1567. return;
  1568. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  1569. InternalSetMaterial( pMaterial );
  1570. meshBuilder.Begin( m_pMesh, MATERIAL_POLYGON, iCount );
  1571. for (int i = 0; i < iCount; ++i)
  1572. {
  1573. meshBuilder.Position3f( ppClippedVerts[i]->m_Position.x, ppClippedVerts[i]->m_Position.y, m_flZPos );
  1574. meshBuilder.Color4ubv( m_DrawColor );
  1575. meshBuilder.TexCoord2fv( 0, ppClippedVerts[i]->m_TexCoord.Base() );
  1576. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1577. }
  1578. meshBuilder.End();
  1579. m_pMesh->Draw();
  1580. }
  1581. else
  1582. {
  1583. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  1584. InternalSetMaterial( pMaterial );
  1585. meshBuilder.Begin( m_pMesh, MATERIAL_POLYGON, n );
  1586. for (int i = 0; i < n; ++i)
  1587. {
  1588. meshBuilder.Position3f( pVertices[i].m_Position.x + m_nTranslateX, pVertices[i].m_Position.y + m_nTranslateY, m_flZPos );
  1589. meshBuilder.Color4ubv( m_DrawColor );
  1590. meshBuilder.TexCoord2fv( 0, pVertices[i].m_TexCoord.Base() );
  1591. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  1592. }
  1593. meshBuilder.End();
  1594. m_pMesh->Draw();
  1595. }
  1596. }
  1597. void CMatSystemSurface::DrawWordBubble( int x0, int y0, int x1, int y1, int nBorderThickness, Color rgbaBackground, Color rgbaBorder, bool bPointer, int nPointerX, int nPointerY, int nPointerBaseThickness )
  1598. {
  1599. int nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1;
  1600. GetClipRect( nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1 );
  1601. SetClipRect( INT16_MIN, INT16_MIN, INT16_MAX, INT16_MAX );
  1602. int nBackgroundWide = x1 - x0;
  1603. int nBackgroundTall = y1 - y0;
  1604. DrawSetColor( rgbaBackground );
  1605. DrawFilledRect( x0, y0, x1, y1 );
  1606. DrawSetTexture( -1 );
  1607. Vector2D vecZero = Vector2D( 0.0f, 0.0f );
  1608. // Figure out the relative position of the thing we're pointing at
  1609. if ( nPointerY >= y0 && nPointerY < y0 + nBackgroundTall )
  1610. {
  1611. // Pointer is pointing inside the bubble!
  1612. bPointer = false;
  1613. }
  1614. int nHalfPointerBaseTopWide, nHalfPointerBaseBottomWide;
  1615. if ( bPointer )
  1616. {
  1617. if ( nPointerY < y0 )
  1618. {
  1619. // Pointing at something above bubble!
  1620. nHalfPointerBaseTopWide = nPointerBaseThickness / 2;
  1621. nHalfPointerBaseBottomWide = nPointerBaseThickness;
  1622. // Draw the up pointer from polygons
  1623. vgui::Vertex_t pointerVerts[ 3 ] =
  1624. {
  1625. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 ), vecZero ),
  1626. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1627. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 ), vecZero )
  1628. };
  1629. DrawTexturedPolygon( 3, pointerVerts );
  1630. }
  1631. else
  1632. {
  1633. // Pointing at something below bubble!
  1634. nHalfPointerBaseTopWide = nPointerBaseThickness;
  1635. nHalfPointerBaseBottomWide = nPointerBaseThickness / 2;
  1636. // Draw the down pointer from polygons
  1637. vgui::Vertex_t pointerVerts[ 3 ] =
  1638. {
  1639. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall ), vecZero ),
  1640. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1641. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall ), vecZero )
  1642. };
  1643. DrawTexturedPolygon( 3, pointerVerts );
  1644. }
  1645. }
  1646. else
  1647. {
  1648. // No pointer so the top and bottom separations are both closed
  1649. nHalfPointerBaseTopWide = nPointerBaseThickness;
  1650. nHalfPointerBaseBottomWide = nPointerBaseThickness;
  1651. }
  1652. // Build a border out of polygons!
  1653. DrawSetColor( rgbaBorder );
  1654. DrawFilledRect( x0, y0 - nBorderThickness, x0 + nHalfPointerBaseTopWide, y0 );
  1655. DrawFilledRect( x0 + nPointerBaseThickness, y0 - nBorderThickness, x0 + nBackgroundWide, y0 );
  1656. DrawFilledRect( x0 - nBorderThickness, y0, x0, y0 + nBackgroundTall );
  1657. DrawFilledRect( x0 + nBackgroundWide, y0, x0 + nBackgroundWide + nBorderThickness, y0 + nBackgroundTall );
  1658. DrawFilledRect( x0, y0 + nBackgroundTall, x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall + nBorderThickness );
  1659. DrawFilledRect( x0 + nPointerBaseThickness, y0 + nBackgroundTall, x0 + nBackgroundWide, y0 + nBackgroundTall + nBorderThickness );
  1660. const int nNumCornerTris = 4;
  1661. vgui::Vertex_t cornerVerts[ nNumCornerTris * 3 ] =
  1662. {
  1663. // Corner TL
  1664. vgui::Vertex_t( Vector2D( x0, y0 - nBorderThickness ), vecZero ),
  1665. vgui::Vertex_t( Vector2D( x0, y0 ), vecZero ),
  1666. vgui::Vertex_t( Vector2D( x0 - nBorderThickness, y0 ), vecZero ),
  1667. // Corner TR
  1668. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 - nBorderThickness ), vecZero ),
  1669. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide + nBorderThickness, y0 ), vecZero ),
  1670. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 ), vecZero ),
  1671. // Corner BL
  1672. vgui::Vertex_t( Vector2D( x0 - nBorderThickness, y0 + nBackgroundTall ), vecZero ),
  1673. vgui::Vertex_t( Vector2D( x0, y0 + nBackgroundTall ), vecZero ),
  1674. vgui::Vertex_t( Vector2D( x0, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  1675. // Corner BR
  1676. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 + nBackgroundTall ), vecZero ),
  1677. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide + nBorderThickness, y0 + nBackgroundTall ), vecZero ),
  1678. vgui::Vertex_t( Vector2D( x0 + nBackgroundWide, y0 + nBackgroundTall + nBorderThickness ), vecZero )
  1679. };
  1680. for ( int nTri = 0; nTri < nNumCornerTris; ++nTri )
  1681. {
  1682. DrawTexturedPolygon( 3, cornerVerts + nTri * 3 );
  1683. }
  1684. if ( bPointer )
  1685. {
  1686. if ( nPointerY < y0 )
  1687. {
  1688. // Draw the up pointer border from polygons
  1689. const int nNumPointerQuads = 3;
  1690. vgui::Vertex_t pointerVerts[ nNumPointerQuads * 4 ] =
  1691. {
  1692. // Pointer left
  1693. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 ), vecZero ),
  1694. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseTopWide, y0 - nBorderThickness ), vecZero ),
  1695. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  1696. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1697. // Pointer right
  1698. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 - nBorderThickness ), vecZero ),
  1699. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 ), vecZero ),
  1700. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1701. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  1702. // Pointer bottom
  1703. vgui::Vertex_t( Vector2D( nPointerX, nPointerY - nBorderThickness * 2 ), vecZero ),
  1704. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY - nBorderThickness ), vecZero ),
  1705. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1706. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY - nBorderThickness ), vecZero )
  1707. };
  1708. for ( int nQuad = 0; nQuad < nNumPointerQuads; ++nQuad )
  1709. {
  1710. DrawTexturedPolygon( 4, pointerVerts + nQuad * 4 );
  1711. }
  1712. }
  1713. else
  1714. {
  1715. // Draw the down pointer from polygons
  1716. const int nNumPointerQuads = 3;
  1717. vgui::Vertex_t pointerVerts[ nNumPointerQuads * 4 ] =
  1718. {
  1719. // Pointer left
  1720. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  1721. vgui::Vertex_t( Vector2D( x0 + nHalfPointerBaseBottomWide, y0 + nBackgroundTall ), vecZero ),
  1722. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1723. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  1724. // Pointer right
  1725. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall + nBorderThickness ), vecZero ),
  1726. vgui::Vertex_t( Vector2D( x0 + nPointerBaseThickness, y0 + nBackgroundTall ), vecZero ),
  1727. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  1728. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1729. // Pointer bottom
  1730. vgui::Vertex_t( Vector2D( nPointerX, nPointerY ), vecZero ),
  1731. vgui::Vertex_t( Vector2D( nPointerX + nBorderThickness, nPointerY + nBorderThickness ), vecZero ),
  1732. vgui::Vertex_t( Vector2D( nPointerX, nPointerY + nBorderThickness * 2 ), vecZero ),
  1733. vgui::Vertex_t( Vector2D( nPointerX - nBorderThickness, nPointerY + nBorderThickness ), vecZero )
  1734. };
  1735. for ( int nQuad = 0; nQuad < nNumPointerQuads; ++nQuad )
  1736. {
  1737. DrawTexturedPolygon( 4, pointerVerts + nQuad * 4 );
  1738. }
  1739. }
  1740. }
  1741. SetClipRect( nOldClipX0, nOldClipY0, nOldClipX1, nOldClipY1 );
  1742. }
  1743. //-----------------------------------------------------------------------------
  1744. //
  1745. // Font-related methods begin here
  1746. //
  1747. //-----------------------------------------------------------------------------
  1748. //-----------------------------------------------------------------------------
  1749. // Purpose: creates a new empty font
  1750. //-----------------------------------------------------------------------------
  1751. HFont CMatSystemSurface::CreateFont()
  1752. {
  1753. MAT_FUNC;
  1754. return FontManager().CreateFont();
  1755. }
  1756. //-----------------------------------------------------------------------------
  1757. // Purpose: adds glyphs to a font created by CreateFont()
  1758. //-----------------------------------------------------------------------------
  1759. bool CMatSystemSurface::SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin, int nRangeMax)
  1760. {
  1761. return FontManager().SetFontGlyphSet(font, windowsFontName, tall, weight, blur, scanlines, flags, nRangeMin, nRangeMax);
  1762. }
  1763. //-----------------------------------------------------------------------------
  1764. // Purpose: adds glyphs to a font created by CreateFont()
  1765. //-----------------------------------------------------------------------------
  1766. bool CMatSystemSurface::SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags)
  1767. {
  1768. return FontManager().SetBitmapFontGlyphSet(font, windowsFontName, scalex, scaley, flags);
  1769. }
  1770. //-----------------------------------------------------------------------------
  1771. // Purpose: returns the max height of a font
  1772. //-----------------------------------------------------------------------------
  1773. int CMatSystemSurface::GetFontTall(HFont font)
  1774. {
  1775. return FontManager().GetFontTall(font);
  1776. }
  1777. //-----------------------------------------------------------------------------
  1778. // Purpose: returns the max height of a font
  1779. //-----------------------------------------------------------------------------
  1780. int CMatSystemSurface::GetFontAscent(HFont font, wchar_t wch)
  1781. {
  1782. return FontManager().GetFontAscent(font,wch);
  1783. }
  1784. //-----------------------------------------------------------------------------
  1785. // Purpose:
  1786. // Input : font -
  1787. // Output : Returns true on success, false on failure.
  1788. //-----------------------------------------------------------------------------
  1789. bool CMatSystemSurface::IsFontAdditive(HFont font)
  1790. {
  1791. return FontManager().IsFontAdditive(font);
  1792. }
  1793. //-----------------------------------------------------------------------------
  1794. // Purpose: returns the abc widths of a single character
  1795. //-----------------------------------------------------------------------------
  1796. void CMatSystemSurface::GetCharABCwide(HFont font, int ch, int &a, int &b, int &c)
  1797. {
  1798. FontManager().GetCharABCwide(font, ch, a, b, c);
  1799. }
  1800. //-----------------------------------------------------------------------------
  1801. // Purpose: returns the pixel width of a single character
  1802. //-----------------------------------------------------------------------------
  1803. int CMatSystemSurface::GetCharacterWidth(HFont font, int ch)
  1804. {
  1805. return FontManager().GetCharacterWidth(font, ch);
  1806. }
  1807. //-----------------------------------------------------------------------------
  1808. // Purpose: returns the kerned width of this char
  1809. //-----------------------------------------------------------------------------
  1810. void CMatSystemSurface::GetKernedCharWidth( HFont font, wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &abcA, float &abcC )
  1811. {
  1812. FontManager().GetKernedCharWidth(font, ch, chBefore, chAfter, wide, abcA, abcC );
  1813. }
  1814. //-----------------------------------------------------------------------------
  1815. // Purpose: returns the area of a text string, including newlines
  1816. //-----------------------------------------------------------------------------
  1817. void CMatSystemSurface::GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall)
  1818. {
  1819. FontManager().GetTextSize(font, text, wide, tall);
  1820. }
  1821. //-----------------------------------------------------------------------------
  1822. // Used by the localization library
  1823. //-----------------------------------------------------------------------------
  1824. int CMatSystemSurface::ComputeTextWidth( const wchar_t *pString )
  1825. {
  1826. int nWide, nTall;
  1827. GetTextSize( 1, pString, nWide, nTall );
  1828. return nWide;
  1829. }
  1830. //-----------------------------------------------------------------------------
  1831. // Purpose: adds a custom font file (supports valve .vfont files)
  1832. //-----------------------------------------------------------------------------
  1833. bool CMatSystemSurface::AddCustomFontFile( const char *fontFileName )
  1834. {
  1835. if ( IsGameConsole() )
  1836. {
  1837. // custom fonts are not supported (not needed) on xbox, all .vfonts are offline converted to ttfs
  1838. // ttfs are mounted/handled elsewhere
  1839. return true;
  1840. }
  1841. char fullPath[MAX_PATH];
  1842. bool bFound = false;
  1843. // windows needs an absolute path for ttf
  1844. bFound = g_pFullFileSystem->GetLocalPath( fontFileName, fullPath, sizeof( fullPath ) ) ? true : false;
  1845. if ( !bFound )
  1846. {
  1847. Warning( "Couldn't find custom font file '%s'\n", fontFileName );
  1848. return false;
  1849. }
  1850. // only add if it's not already in the list
  1851. Q_strlower( fullPath );
  1852. CUtlSymbol sym(fullPath);
  1853. int i;
  1854. for ( i = 0; i < m_CustomFontFileNames.Count(); i++ )
  1855. {
  1856. if ( m_CustomFontFileNames[i] == sym )
  1857. break;
  1858. }
  1859. if ( !m_CustomFontFileNames.IsValidIndex( i ) )
  1860. {
  1861. m_CustomFontFileNames.AddToTail( fullPath );
  1862. if ( IsPC() )
  1863. {
  1864. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  1865. // We don't need the actual file on disk
  1866. #else
  1867. // make sure it's on disk
  1868. // only do this once for each font since in steam it will overwrite the
  1869. // registered font file, causing windows to invalidate the font
  1870. g_pFullFileSystem->GetLocalCopy( fullPath );
  1871. #endif
  1872. }
  1873. }
  1874. #if defined(WIN32)
  1875. #if !defined( _X360 )
  1876. #ifdef SUPPORT_CUSTOM_FONT_FORMAT
  1877. // Just load the font data, decrypt in memory and register for this process
  1878. CUtlBuffer buf;
  1879. if ( !g_pFullFileSystem->ReadFile( fontFileName, NULL, buf ) )
  1880. {
  1881. Msg( "Failed to load custom font file '%s'\n", fontFileName );
  1882. return false;
  1883. }
  1884. if ( !ValveFont::DecodeFont( buf ) )
  1885. {
  1886. Msg( "Failed to parse custom font file '%s'\n", fontFileName );
  1887. return false;
  1888. }
  1889. DWORD dwNumFontsRegistered = 0;
  1890. HANDLE hRegistered = NULL;
  1891. hRegistered = ::AddFontMemResourceEx( buf.Base(), buf.TellPut(), NULL, &dwNumFontsRegistered );
  1892. if ( !hRegistered )
  1893. {
  1894. Msg( "Failed to register custom font file '%s'\n", fontFileName );
  1895. return false;
  1896. }
  1897. m_CustomFontHandles.AddToTail( hRegistered );
  1898. return hRegistered != NULL;
  1899. #else
  1900. // try and use the optimal custom font loader, will makes sure fonts are unloaded properly
  1901. // this function is in a newer version of the gdi library (win2k+), so need to try get it directly
  1902. bool successfullyAdded = false;
  1903. HMODULE gdiModule = ::LoadLibrary("gdi32.dll");
  1904. if (gdiModule)
  1905. {
  1906. typedef int (WINAPI *AddFontResourceExProc)(LPCTSTR, DWORD, PVOID);
  1907. AddFontResourceExProc pAddFontResourceEx = (AddFontResourceExProc)::GetProcAddress(gdiModule, "AddFontResourceExA");
  1908. if (pAddFontResourceEx)
  1909. {
  1910. int result = (*pAddFontResourceEx)(fullPath, 0x10, NULL);
  1911. if (result > 0)
  1912. {
  1913. successfullyAdded = true;
  1914. }
  1915. }
  1916. ::FreeLibrary(gdiModule);
  1917. }
  1918. // add to windows
  1919. bool success = successfullyAdded || (::AddFontResource(fullPath) > 0);
  1920. if ( !success )
  1921. {
  1922. Msg( "Failed to load custom font file '%s'\n", fullPath );
  1923. }
  1924. Assert( success );
  1925. return success;
  1926. #endif
  1927. #endif // X360
  1928. #elif defined( _PS3 )
  1929. return true;
  1930. #elif defined( OSX )
  1931. // Just load the font data, decrypt in memory and register for this process
  1932. CUtlBuffer buf;
  1933. if ( !g_pFullFileSystem->ReadFile( fontFileName, NULL, buf ) )
  1934. {
  1935. Msg( "Failed to load custom font file '%s'\n", fontFileName );
  1936. return false;
  1937. }
  1938. OSStatus err;
  1939. ATSFontContainerRef container;
  1940. err = ATSFontActivateFromMemory( buf.Base(), buf.TellPut(), kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &container );
  1941. if ( err != noErr && ValveFont::DecodeFont( buf ) )
  1942. {
  1943. err = ATSFontActivateFromMemory( buf.Base(), buf.TellPut(), kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, &container );
  1944. }
  1945. #if 0
  1946. if ( err == noErr )
  1947. {
  1948. // Debug code to let you find out the name of a font we pull in from a memory buffer
  1949. // Count the number of fonts that were loaded.
  1950. ItemCount fontCount = 0;
  1951. err = ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 0,
  1952. NULL, &fontCount);
  1953. if (err != noErr || fontCount < 1) {
  1954. return false;
  1955. }
  1956. // Load font from container.
  1957. ATSFontRef font_ref_ats = 0;
  1958. ATSFontFindFromContainer(container, kATSOptionFlagsDefault, 1,
  1959. &font_ref_ats, NULL);
  1960. if (!font_ref_ats) {
  1961. return false;
  1962. }
  1963. CFStringRef name;
  1964. ATSFontGetPostScriptName( font_ref_ats, kATSOptionFlagsDefault, &name );
  1965. const char *font_name = CFStringGetCStringPtr( name, CFStringGetSystemEncoding());
  1966. printf( "loaded %s\n", font_name );
  1967. }
  1968. #endif
  1969. return err == noErr;
  1970. #elif defined(LINUX)
  1971. // Just load the font data, decrypt in memory and register for this process
  1972. CUtlBuffer buf;
  1973. if ( !g_pFullFileSystem->ReadFile( fontFileName, NULL, buf ) )
  1974. {
  1975. Msg( "Failed to load custom font file '%s'\n", fontFileName );
  1976. return false;
  1977. }
  1978. FT_Error error;
  1979. FT_Face face;
  1980. if ( !ValveFont::DecodeFont( buf ) )
  1981. error = FT_New_Face( FontManager().GetFontLibraryHandle(), (const char *)fullPath, 0, &face );
  1982. else
  1983. error = FT_New_Memory_Face( FontManager().GetFontLibraryHandle(), (FT_Byte *)buf.Base(), buf.TellPut(), 0, &face );
  1984. if ( error == FT_Err_Unknown_File_Format )
  1985. {
  1986. return false;
  1987. }
  1988. else if ( error )
  1989. {
  1990. return false;
  1991. }
  1992. const char *pchFontName = FT_Get_Postscript_Name( face );
  1993. if ( !V_stricmp( pchFontName, "TradeGothic" ) )
  1994. pchFontName = "Trade Gothic";
  1995. if ( !V_stricmp( pchFontName, "TradeGothicBold" ) )
  1996. pchFontName = "Trade Gothic Bold";
  1997. if ( !V_stricmp( pchFontName, "Stubble-bold" ) )
  1998. pchFontName = "Stubble bold";
  1999. font_entry entry;
  2000. entry.size = buf.TellPut();
  2001. entry.data = buf.Detach();
  2002. m_FontData.Insert( pchFontName, entry );
  2003. FT_Done_Face ( face );
  2004. return true;
  2005. #else
  2006. #error
  2007. #endif
  2008. }
  2009. #ifdef LINUX
  2010. void *CMatSystemSurface::FontDataHelper( const char *pchFontName, int &size )
  2011. {
  2012. int iIndex = m_FontData.Find( pchFontName );
  2013. if ( iIndex != m_FontData.InvalidIndex() )
  2014. {
  2015. size = m_FontData[ iIndex ].size;
  2016. return m_FontData[ iIndex ].data;
  2017. }
  2018. size = 0;
  2019. return NULL;
  2020. }
  2021. #endif
  2022. //-----------------------------------------------------------------------------
  2023. // Purpose: adds a bitmap font file
  2024. //-----------------------------------------------------------------------------
  2025. bool CMatSystemSurface::AddBitmapFontFile( const char *fontFileName )
  2026. {
  2027. MAT_FUNC;
  2028. bool bFound = false;
  2029. bFound = ( ( g_pFullFileSystem->GetDVDMode() == DVDMODE_STRICT ) || g_pFullFileSystem->FileExists( fontFileName, IsGameConsole() ? "GAME" : NULL ) );
  2030. if ( !bFound )
  2031. {
  2032. Msg( "Couldn't find bitmap font file '%s'\n", fontFileName );
  2033. return false;
  2034. }
  2035. char path[MAX_PATH];
  2036. Q_strncpy( path, fontFileName, MAX_PATH );
  2037. // only add if it's not already in the list
  2038. Q_strlower( path );
  2039. CUtlSymbol sym( path );
  2040. int i;
  2041. for ( i = 0; i < m_BitmapFontFileNames.Count(); i++ )
  2042. {
  2043. if ( m_BitmapFontFileNames[i] == sym )
  2044. break;
  2045. }
  2046. if ( !m_BitmapFontFileNames.IsValidIndex( i ) )
  2047. {
  2048. m_BitmapFontFileNames.AddToTail( path );
  2049. if ( IsPC() )
  2050. {
  2051. // make sure it's on disk
  2052. // only do this once for each font since in steam it will overwrite the
  2053. // registered font file, causing windows to invalidate the font
  2054. g_pFullFileSystem->GetLocalCopy( path );
  2055. }
  2056. }
  2057. return true;
  2058. }
  2059. //-----------------------------------------------------------------------------
  2060. // Purpose:
  2061. //-----------------------------------------------------------------------------
  2062. void CMatSystemSurface::SetBitmapFontName( const char *pName, const char *pFontFilename )
  2063. {
  2064. char fontPath[MAX_PATH];
  2065. Q_strncpy( fontPath, pFontFilename, MAX_PATH );
  2066. Q_strlower( fontPath );
  2067. CUtlSymbol sym( fontPath );
  2068. int i;
  2069. for (i = 0; i < m_BitmapFontFileNames.Count(); i++)
  2070. {
  2071. if ( m_BitmapFontFileNames[i] == sym )
  2072. {
  2073. // found it, update the mapping
  2074. int index = m_BitmapFontFileMapping.Find( pName );
  2075. if ( !m_BitmapFontFileMapping.IsValidIndex( index ) )
  2076. {
  2077. index = m_BitmapFontFileMapping.Insert( pName );
  2078. }
  2079. m_BitmapFontFileMapping.Element( index ) = i;
  2080. break;
  2081. }
  2082. }
  2083. }
  2084. //-----------------------------------------------------------------------------
  2085. // Purpose:
  2086. //-----------------------------------------------------------------------------
  2087. const char *CMatSystemSurface::GetBitmapFontName( const char *pName )
  2088. {
  2089. // find it in the mapping symbol table
  2090. int index = m_BitmapFontFileMapping.Find( pName );
  2091. if ( index == m_BitmapFontFileMapping.InvalidIndex() )
  2092. {
  2093. return "";
  2094. }
  2095. return m_BitmapFontFileNames[m_BitmapFontFileMapping.Element( index )].String();
  2096. }
  2097. void CMatSystemSurface::ClearTemporaryFontCache( void )
  2098. {
  2099. FontManager().ClearTemporaryFontCache();
  2100. }
  2101. //-----------------------------------------------------------------------------
  2102. // Purpose: Force a set of characters to be rendered into the font page.
  2103. //-----------------------------------------------------------------------------
  2104. void CMatSystemSurface::PrecacheFontCharacters( HFont font, wchar_t *pCharacterString )
  2105. {
  2106. if ( !pCharacterString || !pCharacterString[0] )
  2107. {
  2108. return;
  2109. }
  2110. StartDrawing();
  2111. DrawSetTextFont( font );
  2112. int numChars = 0;
  2113. while( pCharacterString[ numChars ] )
  2114. {
  2115. numChars++;
  2116. }
  2117. int *pTextureIDs_ignored = (int *)stackalloc( numChars*sizeof( int ) );
  2118. float **pTexCoords_ignored = (float **)stackalloc( numChars*sizeof( float * ) );
  2119. g_FontTextureCache.GetTextureForChars( m_hCurrentFont, FONT_DRAW_DEFAULT, pCharacterString, pTextureIDs_ignored, pTexCoords_ignored, numChars );
  2120. FinishDrawing();
  2121. }
  2122. const char *CMatSystemSurface::GetFontName( HFont font )
  2123. {
  2124. return FontManager().GetFontName( font );
  2125. }
  2126. //-----------------------------------------------------------------------------
  2127. // Purpose:
  2128. //-----------------------------------------------------------------------------
  2129. void CMatSystemSurface::DrawSetTextFont(HFont font)
  2130. {
  2131. Assert( g_bInDrawing );
  2132. m_hCurrentFont = font;
  2133. }
  2134. //-----------------------------------------------------------------------------
  2135. // Purpose: Renders any batched up text
  2136. //-----------------------------------------------------------------------------
  2137. void CMatSystemSurface::DrawFlushText()
  2138. {
  2139. if ( !m_nBatchedCharVertCount )
  2140. return;
  2141. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
  2142. InternalSetMaterial( pMaterial );
  2143. DrawQuadArray( m_nBatchedCharVertCount / 2, m_BatchedCharVerts, m_DrawTextColor );
  2144. m_nBatchedCharVertCount = 0;
  2145. }
  2146. //-----------------------------------------------------------------------------
  2147. // Sets the text color
  2148. //-----------------------------------------------------------------------------
  2149. void CMatSystemSurface::DrawSetTextColor(int r, int g, int b, int a)
  2150. {
  2151. int adjustedAlpha = (a * m_flAlphaMultiplier);
  2152. if ( r != m_DrawTextColor[0] || g != m_DrawTextColor[1] || b != m_DrawTextColor[2] || adjustedAlpha != m_DrawTextColor[3] )
  2153. {
  2154. // text color changed, flush any existing text
  2155. DrawFlushText();
  2156. m_DrawTextColor[0] = (unsigned char)r;
  2157. m_DrawTextColor[1] = (unsigned char)g;
  2158. m_DrawTextColor[2] = (unsigned char)b;
  2159. m_DrawTextColor[3] = (unsigned char)adjustedAlpha;
  2160. }
  2161. }
  2162. //-----------------------------------------------------------------------------
  2163. // Purpose: alternate color set
  2164. //-----------------------------------------------------------------------------
  2165. void CMatSystemSurface::DrawSetTextColor(Color col)
  2166. {
  2167. DrawSetTextColor(col[0], col[1], col[2], col[3]);
  2168. }
  2169. //-----------------------------------------------------------------------------
  2170. // Purpose: change the scale of a bitmap font
  2171. //-----------------------------------------------------------------------------
  2172. void CMatSystemSurface::DrawSetTextScale(float sx, float sy)
  2173. {
  2174. FontManager().SetFontScale( m_hCurrentFont, sx, sy );
  2175. }
  2176. //-----------------------------------------------------------------------------
  2177. // Text rendering location
  2178. //-----------------------------------------------------------------------------
  2179. void CMatSystemSurface::DrawSetTextPos(int x, int y)
  2180. {
  2181. Assert( g_bInDrawing );
  2182. m_pDrawTextPos[0] = x;
  2183. m_pDrawTextPos[1] = y;
  2184. }
  2185. //-----------------------------------------------------------------------------
  2186. // Purpose:
  2187. //-----------------------------------------------------------------------------
  2188. void CMatSystemSurface::DrawGetTextPos(int& x,int& y)
  2189. {
  2190. Assert( g_bInDrawing );
  2191. x = m_pDrawTextPos[0];
  2192. y = m_pDrawTextPos[1];
  2193. }
  2194. #pragma warning( disable : 4706 )
  2195. //-----------------------------------------------------------------------------
  2196. // Purpose:
  2197. //-----------------------------------------------------------------------------
  2198. void CMatSystemSurface::DrawUnicodeString( const wchar_t *pString, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
  2199. {
  2200. // skip fully transparent characters
  2201. if ( m_DrawTextColor[3] == 0 )
  2202. return;
  2203. //hushed MAT_FUNC;
  2204. #ifdef POSIX
  2205. DrawPrintText( pString, V_wcslen( pString ) , drawType );
  2206. #else
  2207. wchar_t ch;
  2208. while ( ( ch = *pString++ ) )
  2209. {
  2210. DrawUnicodeChar( ch );
  2211. }
  2212. #endif
  2213. }
  2214. #pragma warning( default : 4706 )
  2215. //-----------------------------------------------------------------------------
  2216. // Purpose:
  2217. //-----------------------------------------------------------------------------
  2218. void CMatSystemSurface::DrawUnicodeChar(wchar_t ch, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
  2219. {
  2220. // skip fully transparent characters
  2221. if ( m_DrawTextColor[3] == 0 )
  2222. return;
  2223. FontCharRenderInfo info;
  2224. info.drawType = drawType;
  2225. if ( DrawGetUnicodeCharRenderInfo( ch, info ) )
  2226. {
  2227. DrawRenderCharFromInfo( info );
  2228. }
  2229. }
  2230. //-----------------------------------------------------------------------------
  2231. // Purpose:
  2232. //-----------------------------------------------------------------------------
  2233. bool CMatSystemSurface::DrawGetUnicodeCharRenderInfo( wchar_t ch, FontCharRenderInfo& info )
  2234. {
  2235. Assert( g_bInDrawing );
  2236. info.valid = false;
  2237. if ( !m_hCurrentFont )
  2238. {
  2239. return info.valid;
  2240. }
  2241. PREFETCH360( &m_BatchedCharVerts[ m_nBatchedCharVertCount ], 0 );
  2242. info.valid = true;
  2243. info.ch = ch;
  2244. DrawGetTextPos(info.x, info.y);
  2245. info.currentFont = m_hCurrentFont;
  2246. info.fontTall = GetFontTall(m_hCurrentFont);
  2247. GetCharABCwide(m_hCurrentFont, ch, info.abcA, info.abcB, info.abcC);
  2248. bool bUnderlined = FontManager().GetFontUnderlined( m_hCurrentFont );
  2249. // Do prestep before generating texture coordinates, etc.
  2250. if ( !bUnderlined )
  2251. {
  2252. info.x += info.abcA;
  2253. }
  2254. // get the character texture from the cache
  2255. info.textureId = 0;
  2256. float *texCoords = NULL;
  2257. if (!g_FontTextureCache.GetTextureForChar(m_hCurrentFont, info.drawType, ch, &info.textureId, &texCoords))
  2258. {
  2259. info.valid = false;
  2260. return info.valid;
  2261. }
  2262. // Text will get flushed here if it needs to be.
  2263. DrawSetTexture( info.textureId );
  2264. int fontWide = info.abcB;
  2265. if ( bUnderlined )
  2266. {
  2267. fontWide += ( info.abcA + info.abcC );
  2268. info.x-= info.abcA;
  2269. }
  2270. // This avoid copying the data in the nonclipped case!!! (X360)
  2271. info.verts = &m_BatchedCharVerts[ m_nBatchedCharVertCount ];
  2272. InitVertex( info.verts[0], info.x, info.y, texCoords[0], texCoords[1] );
  2273. InitVertex( info.verts[1], info.x + fontWide, info.y + info.fontTall, texCoords[2], texCoords[3] );
  2274. info.shouldclip = true;
  2275. return info.valid;
  2276. }
  2277. //-----------------------------------------------------------------------------
  2278. // Purpose: batches up characters for rendering
  2279. //-----------------------------------------------------------------------------
  2280. void CMatSystemSurface::DrawRenderCharInternal( const FontCharRenderInfo& info )
  2281. {
  2282. Assert( g_bInDrawing );
  2283. // xbox opts out of pricey/pointless text clipping
  2284. if ( IsPC() && info.shouldclip )
  2285. {
  2286. Vertex_t clip[ 2 ];
  2287. clip[ 0 ] = info.verts[ 0 ];
  2288. clip[ 1 ] = info.verts[ 1 ];
  2289. if ( !ClipRect( clip[0], clip[1], &info.verts[0], &info.verts[1] ) )
  2290. {
  2291. // Fully clipped
  2292. return;
  2293. }
  2294. }
  2295. m_nBatchedCharVertCount += 2;
  2296. if ( m_nBatchedCharVertCount >= MAX_BATCHED_CHAR_VERTS - 2 )
  2297. {
  2298. DrawFlushText();
  2299. }
  2300. }
  2301. //-----------------------------------------------------------------------------
  2302. // Purpose:
  2303. //-----------------------------------------------------------------------------
  2304. void CMatSystemSurface::DrawRenderCharFromInfo( const FontCharRenderInfo& info )
  2305. {
  2306. if ( !info.valid )
  2307. return;
  2308. int x = info.x;
  2309. // get the character texture from the cache
  2310. DrawSetTexture( info.textureId );
  2311. DrawRenderCharInternal( info );
  2312. // Only do post step
  2313. x += ( info.abcB + info.abcC );
  2314. // Update cursor pos
  2315. DrawSetTextPos(x, info.y);
  2316. }
  2317. //-----------------------------------------------------------------------------
  2318. // Renders a text buffer
  2319. //-----------------------------------------------------------------------------
  2320. void CMatSystemSurface::DrawPrintText(const wchar_t *text, int iTextLen, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
  2321. {
  2322. MAT_FUNC;
  2323. CMatRenderContextPtr prc( g_pMaterialSystem );
  2324. Assert( g_bInDrawing );
  2325. if (!text)
  2326. return;
  2327. if (!m_hCurrentFont)
  2328. return;
  2329. int x = m_pDrawTextPos[0] + m_nTranslateX;
  2330. int y = m_pDrawTextPos[1] + m_nTranslateY;
  2331. int iTall = GetFontTall(m_hCurrentFont);
  2332. int iLastTexId = -1;
  2333. int iCount = 0;
  2334. Vertex_t *pQuads = (Vertex_t*)stackalloc((2 * iTextLen) * sizeof(Vertex_t) );
  2335. bool bUnderlined = FontManager().GetFontUnderlined( m_hCurrentFont );
  2336. int iTotalWidth = 0;
  2337. for (int i=0; i<iTextLen; ++i)
  2338. {
  2339. wchar_t ch = text[i];
  2340. int abcA,abcB,abcC;
  2341. GetCharABCwide(m_hCurrentFont, ch, abcA, abcB, abcC);
  2342. //iTotalWidth += abcA;
  2343. float flWide;
  2344. float flabcA;
  2345. float flabcC;
  2346. wchar_t chBefore = 0;
  2347. wchar_t chAfter = 0;
  2348. if ( i > 0 )
  2349. chBefore = text[i-1];
  2350. if ( i < iTextLen )
  2351. chAfter = text[i+1];
  2352. FontManager().GetKernedCharWidth( m_hCurrentFont, ch, chBefore, chAfter, flWide, flabcA, flabcC );
  2353. int textureWide = abcB;
  2354. if ( bUnderlined )
  2355. {
  2356. textureWide += ( abcA + abcC );
  2357. x-= abcA;
  2358. }
  2359. if ( !iswspace( ch ) || bUnderlined )
  2360. {
  2361. // get the character texture from the cache
  2362. int iTexId = 0;
  2363. float *texCoords = NULL;
  2364. if (!g_FontTextureCache.GetTextureForChar(m_hCurrentFont, drawType, ch, &iTexId, &texCoords))
  2365. continue;
  2366. Assert( texCoords );
  2367. if (iTexId != iLastTexId)
  2368. {
  2369. // FIXME: At the moment, we just draw all the batched up
  2370. // text when the font changes. We Should batch up per material
  2371. // and *then* draw
  2372. if (iCount)
  2373. {
  2374. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(iLastTexId);
  2375. InternalSetMaterial( pMaterial );
  2376. DrawQuadArray( iCount, pQuads, m_DrawTextColor );
  2377. iCount = 0;
  2378. }
  2379. iLastTexId = iTexId;
  2380. }
  2381. Vertex_t &ul = pQuads[2*iCount];
  2382. Vertex_t &lr = pQuads[2*iCount + 1];
  2383. ++iCount;
  2384. ul.m_Position.x = x + iTotalWidth + floor(abcA + 0.6);
  2385. ul.m_Position.y = y;
  2386. lr.m_Position.x = ul.m_Position.x + textureWide;
  2387. lr.m_Position.y = ul.m_Position.y + iTall;
  2388. // Gets at the texture coords for this character in its texture page
  2389. /*
  2390. float tex_U0_bias = prc->Knob("tex-U0-bias");
  2391. float tex_V0_bias = prc->Knob("tex-V0-bias");
  2392. float tex_U1_bias = prc->Knob("tex-U1-bias");
  2393. float tex_V1_bias = prc->Knob("tex-V1-bias");
  2394. ul.m_TexCoord[0] = texCoords[0] + tex_U0_bias;
  2395. ul.m_TexCoord[1] = texCoords[1] + tex_V0_bias;
  2396. lr.m_TexCoord[0] = texCoords[2] + tex_U1_bias;
  2397. lr.m_TexCoord[1] = texCoords[3] + tex_V1_bias;
  2398. */
  2399. ul.m_TexCoord[0] = texCoords[0];
  2400. ul.m_TexCoord[1] = texCoords[1];
  2401. lr.m_TexCoord[0] = texCoords[2];
  2402. lr.m_TexCoord[1] = texCoords[3];
  2403. }
  2404. iTotalWidth += floor(flWide+0.6);
  2405. }
  2406. // Draw any left-over characters
  2407. if (iCount)
  2408. {
  2409. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(iLastTexId);
  2410. InternalSetMaterial( pMaterial );
  2411. DrawQuadArray( iCount, pQuads, m_DrawTextColor );
  2412. }
  2413. m_pDrawTextPos[0] += iTotalWidth;
  2414. stackfree(pQuads);
  2415. }
  2416. //-----------------------------------------------------------------------------
  2417. // Returns the screen size
  2418. //-----------------------------------------------------------------------------
  2419. void CMatSystemSurface::GetScreenSize(int &iWide, int &iTall)
  2420. {
  2421. if ( m_ScreenSizeOverride.m_bActive )
  2422. {
  2423. iWide = m_ScreenSizeOverride.m_nValue[ 0 ];
  2424. iTall = m_ScreenSizeOverride.m_nValue[ 1 ];
  2425. return;
  2426. }
  2427. int x, y;
  2428. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2429. pRenderContext->GetViewport( x, y, iWide, iTall );
  2430. }
  2431. bool CMatSystemSurface::ForceScreenSizeOverride( bool bState, int wide, int tall )
  2432. {
  2433. bool bWasSet = m_ScreenSizeOverride.m_bActive;
  2434. m_ScreenSizeOverride.m_bActive = bState;
  2435. m_ScreenSizeOverride.m_nValue[ 0 ] = wide;
  2436. m_ScreenSizeOverride.m_nValue[ 1 ] = tall;
  2437. return bWasSet;
  2438. }
  2439. // LocalToScreen, ParentLocalToScreen fixups for explicit PaintTraverse calls on Panels not at 0, 0 position
  2440. bool CMatSystemSurface::ForceScreenPosOffset( bool bState, int x, int y )
  2441. {
  2442. bool bWasSet = m_ScreenPosOverride.m_bActive;
  2443. m_ScreenPosOverride.m_bActive = bState;
  2444. m_ScreenPosOverride.m_nValue[ 0 ] = x;
  2445. m_ScreenPosOverride.m_nValue[ 1 ] = y;
  2446. return bWasSet;
  2447. }
  2448. void CMatSystemSurface::OffsetAbsPos( int &x, int &y )
  2449. {
  2450. if ( !m_ScreenPosOverride.m_bActive )
  2451. return;
  2452. x += m_ScreenPosOverride.m_nValue[ 0 ];
  2453. y += m_ScreenPosOverride.m_nValue[ 1 ];
  2454. }
  2455. bool CMatSystemSurface::IsScreenSizeOverrideActive( void )
  2456. {
  2457. return ( m_ScreenSizeOverride.m_bActive );
  2458. }
  2459. bool CMatSystemSurface::IsScreenPosOverrideActive( void )
  2460. {
  2461. return ( m_ScreenPosOverride.m_bActive );
  2462. }
  2463. //-----------------------------------------------------------------------------
  2464. // Purpose: Notification of a new screen size
  2465. //-----------------------------------------------------------------------------
  2466. void CMatSystemSurface::OnScreenSizeChanged( int nOldWidth, int nOldHeight )
  2467. {
  2468. int iNewWidth, iNewHeight;
  2469. GetScreenSize( iNewWidth, iNewHeight );
  2470. Msg( "Changing resolutions from (%d, %d) -> (%d, %d)\n", nOldWidth, nOldHeight, iNewWidth, iNewHeight );
  2471. // update the root panel size
  2472. ipanel()->SetSize(m_pEmbeddedPanel, iNewWidth, iNewHeight);
  2473. // notify every panel
  2474. VPANEL panel = GetEmbeddedPanel();
  2475. ivgui()->PostMessage(panel, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWidth, "oldtall", nOldHeight), NULL);
  2476. // only the pc can support a resolution change
  2477. // the schemes/fonts are size based, these need to be redone before the panels make font queries
  2478. // scheme manager will early out if video size change not truly detected (need to match that logic, otherwise fonts won't get rebuilt)
  2479. if ( IsPC() && ( iNewWidth != nOldWidth || iNewHeight != nOldHeight ) )
  2480. {
  2481. // schemes are size based and need to be redone
  2482. ReloadSchemes();
  2483. }
  2484. // Run a frame of the GUI to notify all subwindows of the message size change
  2485. ivgui()->RunFrame();
  2486. }
  2487. // Causes schemes to get reloaded which then causes fonts to get reloaded
  2488. void CMatSystemSurface::ReloadSchemes()
  2489. {
  2490. // Don't do this on game consoles!!!
  2491. // This can't be supported as font work is enormously expensive in terms of memory and i/o
  2492. if ( IsGameConsole() )
  2493. return;
  2494. // clear font texture cache
  2495. g_FontTextureCache.Clear();
  2496. m_iBoundTexture = -1;
  2497. // about to reload schemes, which will reload fonts
  2498. // this wipes away the existing set of underlying resources (otherwise leak)
  2499. FontManager().ClearAllFonts();
  2500. // can now reload schemes which will repopulate the font tables
  2501. scheme()->ReloadSchemes();
  2502. }
  2503. // Causes fonts to get reloaded, etc.
  2504. void CMatSystemSurface::ResetFontCaches()
  2505. {
  2506. // Don't do this on game consoles!!!
  2507. // This can't be supported as font work is enormously expensive in terms of memory and i/o
  2508. if ( IsGameConsole() )
  2509. return;
  2510. // clear font texture cache
  2511. g_FontTextureCache.Clear();
  2512. m_iBoundTexture = -1;
  2513. // reload fonts
  2514. FontManager().ClearAllFonts();
  2515. scheme()->ReloadFonts();
  2516. }
  2517. //-----------------------------------------------------------------------------
  2518. // Returns the size of the embedded panel
  2519. //-----------------------------------------------------------------------------
  2520. void CMatSystemSurface::GetWorkspaceBounds(int &x, int &y, int &iWide, int &iTall)
  2521. {
  2522. if ( m_ScreenSizeOverride.m_bActive )
  2523. {
  2524. x = y = 0;
  2525. iWide = m_ScreenSizeOverride.m_nValue[ 0 ];
  2526. iTall = m_ScreenSizeOverride.m_nValue[ 1 ];
  2527. return;
  2528. }
  2529. // NOTE: This is equal to the viewport size by default,
  2530. // but other embedded panels can be used
  2531. x = m_WorkSpaceInsets[0];
  2532. y = m_WorkSpaceInsets[1];
  2533. g_pVGuiPanel->GetSize(m_pEmbeddedPanel, iWide, iTall);
  2534. iWide -= m_WorkSpaceInsets[2];
  2535. iTall -= m_WorkSpaceInsets[3];
  2536. }
  2537. //-----------------------------------------------------------------------------
  2538. // Purpose:
  2539. //-----------------------------------------------------------------------------
  2540. void CMatSystemSurface::SetWorkspaceInsets( int left, int top, int right, int bottom )
  2541. {
  2542. m_WorkSpaceInsets[0] = left;
  2543. m_WorkSpaceInsets[1] = top;
  2544. m_WorkSpaceInsets[2] = right;
  2545. m_WorkSpaceInsets[3] = bottom;
  2546. }
  2547. //-----------------------------------------------------------------------------
  2548. // A bunch of methods needed for the windows version only
  2549. //-----------------------------------------------------------------------------
  2550. void CMatSystemSurface::SetAsTopMost(VPANEL panel, bool state)
  2551. {
  2552. }
  2553. void CMatSystemSurface::SetAsToolBar(VPANEL panel, bool state) // removes the window's task bar entry (for context menu's, etc.)
  2554. {
  2555. }
  2556. void CMatSystemSurface::SetForegroundWindow (VPANEL panel)
  2557. {
  2558. BringToFront(panel);
  2559. }
  2560. void CMatSystemSurface::SetPanelVisible(VPANEL panel, bool state)
  2561. {
  2562. }
  2563. void CMatSystemSurface::SetMinimized(VPANEL panel, bool state)
  2564. {
  2565. if (state)
  2566. {
  2567. g_pVGuiPanel->SetPlat(panel, VPANEL_MINIMIZED);
  2568. g_pVGuiPanel->SetVisible(panel, false);
  2569. }
  2570. else
  2571. {
  2572. g_pVGuiPanel->SetPlat(panel, VPANEL_NORMAL);
  2573. }
  2574. }
  2575. bool CMatSystemSurface::IsMinimized(vgui::VPANEL panel)
  2576. {
  2577. return (g_pVGuiPanel->Plat(panel) == VPANEL_MINIMIZED);
  2578. }
  2579. void CMatSystemSurface::FlashWindow(VPANEL panel, bool state)
  2580. {
  2581. }
  2582. //-----------------------------------------------------------------------------
  2583. // Purpose:
  2584. //-----------------------------------------------------------------------------
  2585. void CMatSystemSurface::SetTitle(VPANEL panel, const wchar_t *title)
  2586. {
  2587. int entry = GetTitleEntry( panel );
  2588. if ( entry == -1 )
  2589. {
  2590. entry = m_Titles.AddToTail();
  2591. }
  2592. TitleEntry *e = &m_Titles[ entry ];
  2593. Assert( e );
  2594. wcsncpy( e->title, title, sizeof( e->title )/ sizeof( wchar_t ) );
  2595. e->panel = panel;
  2596. }
  2597. //-----------------------------------------------------------------------------
  2598. // Purpose:
  2599. //-----------------------------------------------------------------------------
  2600. wchar_t const *CMatSystemSurface::GetTitle( VPANEL panel )
  2601. {
  2602. int entry = GetTitleEntry( panel );
  2603. if ( entry != -1 )
  2604. {
  2605. TitleEntry *e = &m_Titles[ entry ];
  2606. return e->title;
  2607. }
  2608. return NULL;
  2609. }
  2610. //-----------------------------------------------------------------------------
  2611. // Purpose: Private lookup method
  2612. // Input : *panel -
  2613. // Output : TitleEntry
  2614. //-----------------------------------------------------------------------------
  2615. int CMatSystemSurface::GetTitleEntry( vgui::VPANEL panel )
  2616. {
  2617. for ( int i = 0; i < m_Titles.Count(); i++ )
  2618. {
  2619. TitleEntry* entry = &m_Titles[ i ];
  2620. if ( entry->panel == panel )
  2621. return i;
  2622. }
  2623. return -1;
  2624. }
  2625. void CMatSystemSurface::SwapBuffers(VPANEL panel)
  2626. {
  2627. }
  2628. void CMatSystemSurface::Invalidate(VPANEL panel)
  2629. {
  2630. }
  2631. void CMatSystemSurface::ApplyChanges()
  2632. {
  2633. }
  2634. // notify icons?!?
  2635. VPANEL CMatSystemSurface::GetNotifyPanel()
  2636. {
  2637. return NULL;
  2638. }
  2639. void CMatSystemSurface::SetNotifyIcon(VPANEL context, HTexture icon, VPANEL panelToReceiveMessages, const char *text)
  2640. {
  2641. }
  2642. bool CMatSystemSurface::IsWithin(int x, int y)
  2643. {
  2644. return true;
  2645. }
  2646. bool CMatSystemSurface::ShouldPaintChildPanel(VPANEL childPanel)
  2647. {
  2648. if ( m_pRestrictedPanel && ( m_pRestrictedPanel != childPanel ) &&
  2649. !g_pVGuiPanel->HasParent( childPanel, m_pRestrictedPanel ) )
  2650. {
  2651. return false;
  2652. }
  2653. bool isPopup = ipanel()->IsPopup(childPanel);
  2654. return !isPopup;
  2655. }
  2656. bool CMatSystemSurface::RecreateContext(VPANEL panel)
  2657. {
  2658. return false;
  2659. }
  2660. //-----------------------------------------------------------------------------
  2661. // Focus-related methods
  2662. //-----------------------------------------------------------------------------
  2663. bool CMatSystemSurface::HasFocus()
  2664. {
  2665. return true;
  2666. }
  2667. void CMatSystemSurface::BringToFront(VPANEL panel)
  2668. {
  2669. // move panel to top of list
  2670. g_pVGuiPanel->MoveToFront(panel);
  2671. // move panel to top of popup list
  2672. if ( g_pVGuiPanel->IsPopup( panel ) )
  2673. {
  2674. MovePopupToFront( panel );
  2675. }
  2676. }
  2677. // engine-only focus handling (replacing WM_FOCUS windows handling)
  2678. void CMatSystemSurface::SetTopLevelFocus(VPANEL pSubFocus)
  2679. {
  2680. // walk up the hierarchy until we find what popup panel belongs to
  2681. while (pSubFocus)
  2682. {
  2683. if (ipanel()->IsPopup(pSubFocus) && ipanel()->IsMouseInputEnabled(pSubFocus))
  2684. {
  2685. BringToFront(pSubFocus);
  2686. break;
  2687. }
  2688. pSubFocus = ipanel()->GetParent(pSubFocus);
  2689. }
  2690. }
  2691. //-----------------------------------------------------------------------------
  2692. // Installs a function to play sounds
  2693. //-----------------------------------------------------------------------------
  2694. void CMatSystemSurface::InstallPlaySoundFunc( PlaySoundFunc_t soundFunc )
  2695. {
  2696. m_PlaySoundFunc = soundFunc;
  2697. }
  2698. //-----------------------------------------------------------------------------
  2699. // plays a sound
  2700. //-----------------------------------------------------------------------------
  2701. void CMatSystemSurface::PlaySound(const char *pFileName)
  2702. {
  2703. if (m_PlaySoundFunc)
  2704. m_PlaySoundFunc( pFileName );
  2705. }
  2706. //-----------------------------------------------------------------------------
  2707. // handles mouse movement
  2708. //-----------------------------------------------------------------------------
  2709. void CMatSystemSurface::SetCursorPos(int x, int y)
  2710. {
  2711. CursorSetPos( GetInputContext(), x, y );
  2712. }
  2713. void CMatSystemSurface::GetCursorPos(int &x, int &y)
  2714. {
  2715. CursorGetPos( GetInputContext(), x, y );
  2716. }
  2717. void CMatSystemSurface::SetCursor(HCursor hCursor)
  2718. {
  2719. if ( IsCursorLocked() )
  2720. return;
  2721. if ( _currentCursor != hCursor )
  2722. {
  2723. _currentCursor = hCursor;
  2724. CursorSelect( GetInputContext(), hCursor );
  2725. }
  2726. }
  2727. void CMatSystemSurface::EnableMouseCapture( VPANEL panel, bool state )
  2728. {
  2729. g_pInputStackSystem->SetMouseCapture( GetInputContext(), state );
  2730. }
  2731. //-----------------------------------------------------------------------------
  2732. // Purpose: Turns the panel into a standalone window
  2733. //-----------------------------------------------------------------------------
  2734. void CMatSystemSurface::CreatePopup(VPANEL panel, bool minimized, bool showTaskbarIcon, bool disabled , bool mouseInput , bool kbInput)
  2735. {
  2736. if (!g_pVGuiPanel->GetParent(panel))
  2737. {
  2738. g_pVGuiPanel->SetParent(panel, GetEmbeddedPanel());
  2739. }
  2740. ((VPanel *)panel)->SetPopup(true);
  2741. ((VPanel *)panel)->SetKeyBoardInputEnabled(kbInput);
  2742. ((VPanel *)panel)->SetMouseInputEnabled(mouseInput);
  2743. if ( m_PopupList.Find( panel ) == m_PopupList.InvalidIndex() )
  2744. {
  2745. m_PopupList.AddToTail( panel );
  2746. }
  2747. else
  2748. {
  2749. MovePopupToFront( panel );
  2750. }
  2751. }
  2752. //-----------------------------------------------------------------------------
  2753. // Create/destroy panels..
  2754. //-----------------------------------------------------------------------------
  2755. void CMatSystemSurface::AddPanel(VPANEL panel)
  2756. {
  2757. if (g_pVGuiPanel->IsPopup(panel))
  2758. {
  2759. // turn it into a popup menu
  2760. CreatePopup(panel, false);
  2761. }
  2762. }
  2763. void CMatSystemSurface::ReleasePanel(VPANEL panel)
  2764. {
  2765. // Remove from popup list if needed and remove any dead popups while we're at it
  2766. RemovePopup( panel );
  2767. int entry = GetTitleEntry( panel );
  2768. if ( entry != -1 )
  2769. {
  2770. m_Titles.Remove( entry );
  2771. }
  2772. }
  2773. void CMatSystemSurface::ResetPopupList()
  2774. {
  2775. m_PopupList.RemoveAll();
  2776. }
  2777. void CMatSystemSurface::AddPopup( VPANEL panel )
  2778. {
  2779. if ( m_PopupList.Find( panel ) == m_PopupList.InvalidIndex() )
  2780. {
  2781. m_PopupList.AddToTail( panel );
  2782. }
  2783. }
  2784. void CMatSystemSurface::RemovePopup( vgui::VPANEL panel )
  2785. {
  2786. // Remove from popup list if needed and remove any dead popups while we're at it
  2787. int c = GetPopupCount();
  2788. for ( int i = c - 1; i >= 0 ; i-- )
  2789. {
  2790. VPANEL popup = GetPopup(i );
  2791. if ( popup != panel )
  2792. continue;
  2793. m_PopupList.Remove( i );
  2794. break;
  2795. }
  2796. }
  2797. //-----------------------------------------------------------------------------
  2798. // Methods associated with iterating + drawing the panel tree
  2799. //-----------------------------------------------------------------------------
  2800. void CMatSystemSurface::AddPopupsToList( VPANEL panel )
  2801. {
  2802. if (!g_pVGuiPanel->IsVisible(panel))
  2803. return;
  2804. // Add to popup list as we visit popups
  2805. // Note: popup list is cleared in RunFrame which occurs before this call!!!
  2806. if ( g_pVGuiPanel->IsPopup( panel ) )
  2807. {
  2808. AddPopup( panel );
  2809. }
  2810. int count = g_pVGuiPanel->GetChildCount(panel);
  2811. for (int i = 0; i < count; ++i)
  2812. {
  2813. VPANEL child = g_pVGuiPanel->GetChild(panel, i);
  2814. AddPopupsToList( child );
  2815. }
  2816. }
  2817. //-----------------------------------------------------------------------------
  2818. // Purpose: recurses the panels calculating absolute positions
  2819. // parents must be solved before children
  2820. //-----------------------------------------------------------------------------
  2821. void CMatSystemSurface::InternalSolveTraverse(VPANEL panel)
  2822. {
  2823. VPanel * RESTRICT vp = (VPanel *)panel;
  2824. // solve the parent
  2825. vp->Solve();
  2826. CUtlVector< VPanel * > &children = vp->GetChildren();
  2827. // now we can solve the children
  2828. int c = children.Count();
  2829. for (int i = 0; i < c; ++i)
  2830. {
  2831. VPanel *child = children[ i ];
  2832. if (child->IsVisible())
  2833. {
  2834. InternalSolveTraverse((VPANEL)child);
  2835. }
  2836. }
  2837. }
  2838. //-----------------------------------------------------------------------------
  2839. // Purpose: recurses the panels giving them a chance to do a user-defined think,
  2840. // PerformLayout and ApplySchemeSettings
  2841. // must be done child before parent
  2842. //-----------------------------------------------------------------------------
  2843. void CMatSystemSurface::InternalThinkTraverse(VPANEL panel)
  2844. {
  2845. VPanel * RESTRICT vp = (VPanel *)panel;
  2846. // think the parent
  2847. vp->Client()->Think();
  2848. CUtlVector< VPanel * > &children = vp->GetChildren();
  2849. // and then the children...
  2850. int c = children.Count();
  2851. for (int i = 0; i < c; ++i)
  2852. {
  2853. VPanel *child = children[ i ];
  2854. if ( child->IsVisible() )
  2855. {
  2856. InternalThinkTraverse((VPANEL)child);
  2857. }
  2858. }
  2859. }
  2860. //-----------------------------------------------------------------------------
  2861. // Purpose: recurses the panels giving them a chance to do apply settings,
  2862. //-----------------------------------------------------------------------------
  2863. void CMatSystemSurface::InternalSchemeSettingsTraverse(VPANEL panel, bool forceApplySchemeSettings)
  2864. {
  2865. VPanel * RESTRICT vp = (VPanel *)panel;
  2866. CUtlVector< VPanel * > &children = vp->GetChildren();
  2867. // apply to the children...
  2868. int c = children.Count();
  2869. for (int i = 0; i < c; ++i)
  2870. {
  2871. VPanel *child = children[ i ];
  2872. if ( forceApplySchemeSettings || child->IsVisible() )
  2873. {
  2874. InternalSchemeSettingsTraverse((VPANEL)child, forceApplySchemeSettings);
  2875. }
  2876. }
  2877. // and then the parent
  2878. vp->Client()->PerformApplySchemeSettings();
  2879. }
  2880. //-----------------------------------------------------------------------------
  2881. // Purpose: Walks through the panel tree calling Solve() on them all, in order
  2882. //-----------------------------------------------------------------------------
  2883. void CMatSystemSurface::SolveTraverse(VPANEL panel, bool forceApplySchemeSettings)
  2884. {
  2885. {
  2886. VPROF( "InternalSchemeSettingsTraverse" );
  2887. InternalSchemeSettingsTraverse(panel, forceApplySchemeSettings);
  2888. }
  2889. {
  2890. VPROF( "InternalThinkTraverse" );
  2891. InternalThinkTraverse(panel);
  2892. }
  2893. {
  2894. VPROF( "InternalSolveTraverse" );
  2895. InternalSolveTraverse(panel);
  2896. }
  2897. }
  2898. //-----------------------------------------------------------------------------
  2899. // Purpose: Restricts rendering to a single panel
  2900. //-----------------------------------------------------------------------------
  2901. void CMatSystemSurface::RestrictPaintToSinglePanel( VPANEL panel, bool bForceAllowNonModalSurface )
  2902. {
  2903. if ( !bForceAllowNonModalSurface && panel && m_pRestrictedPanel && m_pRestrictedPanel == input()->GetAppModalSurface() )
  2904. {
  2905. return; // don't restrict drawing to a panel other than the modal one - that's a good way to hang the game.
  2906. }
  2907. m_pRestrictedPanel = panel;
  2908. if ( !panel && m_bRestrictedPanelOverrodeAppModalPanel )
  2909. {
  2910. // Unrestricting after previously restricting to a non-app modal panel.
  2911. input()->SetAppModalSurface( NULL );
  2912. m_bRestrictedPanelOverrodeAppModalPanel = false;
  2913. return;
  2914. }
  2915. VPANEL pAppModal = input()->GetAppModalSurface();
  2916. if ( !pAppModal )
  2917. {
  2918. input()->SetAppModalSurface( panel ); // if painting is restricted to this panel, it had better be modal, or else you can get in some bad state...
  2919. m_bRestrictedPanelOverrodeAppModalPanel = true;
  2920. }
  2921. }
  2922. //-----------------------------------------------------------------------------
  2923. // Is a panel under the restricted panel?
  2924. //-----------------------------------------------------------------------------
  2925. bool CMatSystemSurface::IsPanelUnderRestrictedPanel( VPANEL panel )
  2926. {
  2927. if ( !m_pRestrictedPanel )
  2928. return true;
  2929. while ( panel )
  2930. {
  2931. if ( panel == m_pRestrictedPanel )
  2932. return true;
  2933. panel = ipanel()->GetParent( panel );
  2934. }
  2935. return false;
  2936. }
  2937. //-----------------------------------------------------------------------------
  2938. // Main entry point for painting
  2939. //-----------------------------------------------------------------------------
  2940. void CMatSystemSurface::PaintTraverseEx(VPANEL panel, bool paintPopups /*= false*/ )
  2941. {
  2942. MAT_FUNC;
  2943. if ( !ipanel()->IsVisible( panel ) )
  2944. return;
  2945. VPROF( "CMatSystemSurface::PaintTraverse" );
  2946. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  2947. bool bTopLevelDraw = false;
  2948. ShaderStencilState_t state;
  2949. if ( g_bInDrawing == false )
  2950. {
  2951. // only set the 2d ortho mode once
  2952. bTopLevelDraw = true;
  2953. StartDrawing();
  2954. // clear z + stencil buffer
  2955. // NOTE: Stencil is used to get 3D painting in vgui panels working correctly
  2956. pRenderContext->ClearBuffers( false, true, true );
  2957. state.m_bEnable = true;
  2958. state.m_FailOp = SHADER_STENCILOP_KEEP;
  2959. state.m_ZFailOp = SHADER_STENCILOP_KEEP;
  2960. state.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE;
  2961. state.m_CompareFunc = SHADER_STENCILFUNC_GEQUAL;
  2962. state.m_nReferenceValue = 0;
  2963. state.m_nTestMask = 0xFFFFFFFF;
  2964. state.m_nWriteMask = 0xFFFFFFFF;
  2965. m_nCurrReferenceValue = 0;
  2966. pRenderContext->SetStencilState( state );
  2967. }
  2968. float flOldZPos = m_flZPos;
  2969. // NOTE You might expect we'd have to draw these under the popups so they would occlude
  2970. // them, but there are a few things we do have to draw on top of, esp. the black
  2971. // panel that draws over the top of the engine to darken everything.
  2972. m_flZPos = 0.0f;
  2973. if ( panel == GetEmbeddedPanel() )
  2974. {
  2975. if ( m_pRestrictedPanel )
  2976. {
  2977. // Paint the restricted panel, and its parent.
  2978. // NOTE: This call has guards to not draw popups. If the restricted panel
  2979. // is a popup, it won't draw here.
  2980. ipanel()->PaintTraverse( ipanel()->GetParent( m_pRestrictedPanel ), true );
  2981. }
  2982. else
  2983. {
  2984. // paint traverse the root panel, painting all children
  2985. VPROF( "ipanel()->PaintTraverse" );
  2986. ipanel()->PaintTraverse( panel, true );
  2987. }
  2988. }
  2989. else
  2990. {
  2991. // If it's a popup, it should already have been painted above
  2992. VPROF( "ipanel()->PaintTraverse" );
  2993. if ( !paintPopups || !ipanel()->IsPopup( panel ) )
  2994. {
  2995. ipanel()->PaintTraverse( panel, true );
  2996. }
  2997. }
  2998. // draw the popups
  2999. if ( paintPopups )
  3000. {
  3001. // now draw the popups front to back
  3002. // since depth-test and depth-write are on, the front panels will occlude the underlying ones
  3003. {
  3004. VPROF( "CMatSystemSurface::PaintTraverse popups loop" );
  3005. int popups = m_PopupList.Count();
  3006. // HACK! Using stencil ref 254 so drag/drop helper can use 255.
  3007. int nStencilRef = 254;
  3008. for ( int i = popups - 1; i >= 0; --i )
  3009. {
  3010. VPANEL popupPanel = m_PopupList[ i ];
  3011. if ( !ipanel()->IsFullyVisible( popupPanel ) )
  3012. continue;
  3013. if ( !IsPanelUnderRestrictedPanel( popupPanel ) )
  3014. continue;
  3015. // This makes sure the drag/drop helper is always the first thing drawn
  3016. bool bIsTopmostPopup = ( (VPanel *)popupPanel )->IsTopmostPopup();
  3017. // set our z position
  3018. m_nCurrReferenceValue = bIsTopmostPopup ? 255 : nStencilRef;
  3019. state.m_nReferenceValue = m_nCurrReferenceValue;
  3020. pRenderContext->SetStencilState( state );
  3021. if ( nStencilRef < 1 )
  3022. {
  3023. Warning( "Too many popups! Rendering will be bad!\n" );
  3024. }
  3025. --nStencilRef;
  3026. m_flZPos = ((float)(i) / (float)popups);
  3027. ipanel()->PaintTraverse( popupPanel, true );
  3028. }
  3029. }
  3030. }
  3031. // Restore the old Z Pos
  3032. m_flZPos = flOldZPos;
  3033. if ( bTopLevelDraw )
  3034. {
  3035. // only undo the 2d ortho mode once
  3036. VPROF( "FinishDrawing" );
  3037. // Reset stencil to normal state
  3038. state.m_bEnable = false;
  3039. pRenderContext->SetStencilState( state );
  3040. FinishDrawing();
  3041. }
  3042. }
  3043. //-----------------------------------------------------------------------------
  3044. // Draw a panel
  3045. //-----------------------------------------------------------------------------
  3046. void CMatSystemSurface::PaintTraverse(VPANEL panel)
  3047. {
  3048. PaintTraverseEx( panel, false );
  3049. }
  3050. //-----------------------------------------------------------------------------
  3051. // Begins, ends 3D painting from within a panel paint() method
  3052. //-----------------------------------------------------------------------------
  3053. void CMatSystemSurface::Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom, bool bSupersampleRT )
  3054. {
  3055. MAT_FUNC;
  3056. Assert( iRight > iLeft );
  3057. Assert( iBottom > iTop );
  3058. // Can't use this while drawing in the 3D world since it relies on
  3059. // whacking the shared depth buffer
  3060. Assert( !m_bDrawingIn3DWorld );
  3061. if ( m_bDrawingIn3DWorld )
  3062. return;
  3063. m_n3DLeft = iLeft;
  3064. m_n3DRight = iRight;
  3065. m_n3DTop = iTop;
  3066. m_n3DBottom = iBottom;
  3067. // Can't use this feature when drawing into the 3D world
  3068. Assert( !m_bDrawingIn3DWorld );
  3069. Assert( !m_bIn3DPaintMode );
  3070. m_bIn3DPaintMode = true;
  3071. // Save off the matrices in case the painting method changes them.
  3072. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  3073. pRenderContext->MatrixMode( MATERIAL_MODEL );
  3074. pRenderContext->PushMatrix();
  3075. pRenderContext->MatrixMode( MATERIAL_VIEW );
  3076. pRenderContext->PushMatrix();
  3077. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  3078. pRenderContext->PushMatrix();
  3079. // For 3d painting, use the off-screen render target the material system allocates
  3080. // NOTE: We have to grab it here, as opposed to during init,
  3081. // because the mode hasn't been set by now.
  3082. if ( !m_FullScreenBuffer )
  3083. {
  3084. m_FullScreenBuffer.Init( materials->FindTexture( m_FullScreenBufferName, "render targets" ) );
  3085. }
  3086. if ( !bSupersampleRT || IsX360() )
  3087. {
  3088. m_n3DViewportWidth = iRight - iLeft;
  3089. m_n3DViewportHeight = iBottom - iTop;
  3090. }
  3091. else
  3092. {
  3093. m_n3DViewportWidth = m_FullScreenBuffer->GetActualWidth();
  3094. m_n3DViewportHeight = m_FullScreenBuffer->GetActualHeight();
  3095. // See if we can safely double the resolution
  3096. if ( ( m_n3DViewportWidth >= ( iRight - iLeft )*2 ) && ( m_n3DViewportHeight >= ( iBottom - iTop )*2 ) )
  3097. {
  3098. m_n3DViewportWidth = ( iRight - iLeft )*2;
  3099. m_n3DViewportHeight = ( iBottom - iTop )*2;
  3100. }
  3101. // See if we have more RT space to enlarge the buffer for supersampling
  3102. else if ( ( m_n3DViewportWidth > iRight - iLeft ) && ( m_n3DViewportHeight > iBottom - iTop ) && ( iRight - iLeft > 0 ) && ( iBottom - iTop > 0 ) )
  3103. {
  3104. double dblWidthFactor = double( m_n3DViewportWidth ) / double( iRight - iLeft );
  3105. double dblHeightFactor = double( m_n3DViewportHeight ) / double( iBottom - iTop );
  3106. if ( dblWidthFactor < dblHeightFactor )
  3107. {
  3108. m_n3DViewportHeight = MIN( int( ( iBottom - iTop ) * dblWidthFactor ), m_n3DViewportHeight );
  3109. }
  3110. else
  3111. {
  3112. m_n3DViewportWidth = MIN( int( ( iRight - iLeft ) * dblHeightFactor ), m_n3DViewportWidth );
  3113. }
  3114. }
  3115. else
  3116. {
  3117. // We have to stick with the non-supersampled dimensions because we failed
  3118. // to fit a supersampled size into our render target
  3119. m_n3DViewportWidth = iRight - iLeft;
  3120. m_n3DViewportHeight = iBottom - iTop;
  3121. }
  3122. }
  3123. // FIXME: Set the viewport to match the clip rectangle?
  3124. // Set the viewport to match the scissor rectangle
  3125. pRenderContext->PushRenderTargetAndViewport( m_FullScreenBuffer,
  3126. 0, 0, m_n3DViewportWidth, m_n3DViewportHeight );
  3127. pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
  3128. // Don't draw the 3D scene w/ stencil
  3129. ShaderStencilState_t state;
  3130. state.m_bEnable = false;
  3131. pRenderContext->SetStencilState( state );
  3132. }
  3133. void CMatSystemSurface::End3DPaint( bool bIgnoreAlphaWhenCompositing )
  3134. {
  3135. MAT_FUNC;
  3136. // Can't use this feature when drawing into the 3D world
  3137. Assert( !m_bDrawingIn3DWorld );
  3138. Assert( m_bIn3DPaintMode );
  3139. m_bIn3DPaintMode = false;
  3140. // Reset stencil to set stencil everywhere we draw
  3141. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  3142. ShaderStencilState_t state;
  3143. state.m_bEnable = true;
  3144. state.m_FailOp = SHADER_STENCILOP_KEEP;
  3145. state.m_ZFailOp = SHADER_STENCILOP_KEEP;
  3146. state.m_PassOp = SHADER_STENCILOP_SET_TO_REFERENCE;
  3147. state.m_CompareFunc = SHADER_STENCILFUNC_GEQUAL;
  3148. state.m_nReferenceValue = m_nCurrReferenceValue;
  3149. state.m_nTestMask = 0xFFFFFFFF;
  3150. state.m_nWriteMask = 0xFFFFFFFF;
  3151. pRenderContext->SetStencilState( state );
  3152. // Restore the matrices
  3153. pRenderContext->MatrixMode( MATERIAL_MODEL );
  3154. pRenderContext->PopMatrix();
  3155. pRenderContext->MatrixMode( MATERIAL_VIEW );
  3156. pRenderContext->PopMatrix();
  3157. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  3158. pRenderContext->PopMatrix();
  3159. if ( IsX360() )
  3160. {
  3161. Rect_t rect;
  3162. rect.x = rect.y = 0;
  3163. rect.width = m_n3DRight - m_n3DLeft;
  3164. rect.height = m_n3DBottom - m_n3DTop;
  3165. ITexture *pRtModelPanelTexture = g_pMaterialSystem->FindTexture( MODEL_PANEL_RT_NAME, TEXTURE_GROUP_RENDER_TARGET );
  3166. int nMaxWidth = pRtModelPanelTexture->GetActualWidth();
  3167. int nMaxHeight = pRtModelPanelTexture->GetActualHeight();
  3168. rect.width = MIN( rect.width, nMaxWidth );
  3169. rect.height = MIN( rect.height, nMaxHeight );
  3170. pRenderContext->CopyRenderTargetToTextureEx( pRtModelPanelTexture, 0, &rect, &rect );
  3171. }
  3172. // Restore the viewport (it was stored off in StartDrawing)
  3173. pRenderContext->PopRenderTargetAndViewport();
  3174. pRenderContext->CullMode(MATERIAL_CULLMODE_CCW);
  3175. // Draw the full-screen buffer into the panel
  3176. DrawFullScreenBuffer( m_n3DLeft, m_n3DTop, m_n3DRight, m_n3DBottom, m_n3DViewportWidth, m_n3DViewportHeight, bIgnoreAlphaWhenCompositing );
  3177. // ReSet the material state
  3178. InternalSetMaterial( NULL );
  3179. }
  3180. //-----------------------------------------------------------------------------
  3181. // Gets texture coordinates for drawing the full screen buffer
  3182. //-----------------------------------------------------------------------------
  3183. void CMatSystemSurface::GetFullScreenTexCoords( int x, int y, int w, int h, float *pMinU, float *pMinV, float *pMaxU, float *pMaxV )
  3184. {
  3185. int nTexWidth = m_FullScreenBuffer->GetActualWidth();
  3186. int nTexHeight = m_FullScreenBuffer->GetActualHeight();
  3187. float flOOWidth = 1.0f / nTexWidth;
  3188. float flOOHeight = 1.0f / nTexHeight;
  3189. *pMinU = ( (float)x + 0.5f ) * flOOWidth;
  3190. *pMinV = ( (float)y + 0.5f ) * flOOHeight;
  3191. *pMaxU = ( (float)(x+w) - 0.5f ) * flOOWidth;
  3192. *pMaxV = ( (float)(y+h) - 0.5f ) * flOOHeight;
  3193. }
  3194. //-----------------------------------------------------------------------------
  3195. // Draws the fullscreen buffer into the panel
  3196. //-----------------------------------------------------------------------------
  3197. void CMatSystemSurface::DrawFullScreenBuffer( int nLeft, int nTop, int nRight, int nBottom, int nOffscreenWidth, int nOffscreenHeight, bool bIgnoreAlphaWhenCompositing )
  3198. {
  3199. MAT_FUNC;
  3200. // Draw a textured rectangle over the area
  3201. if ( bIgnoreAlphaWhenCompositing )
  3202. {
  3203. if ( m_nFullScreenBufferMaterialIgnoreAlphaId == -1 )
  3204. {
  3205. m_nFullScreenBufferMaterialIgnoreAlphaId = CreateNewTextureID();
  3206. DrawSetTextureMaterial( m_nFullScreenBufferMaterialIgnoreAlphaId, m_FullScreenBufferMaterialIgnoreAlpha );
  3207. }
  3208. }
  3209. else
  3210. {
  3211. if ( m_nFullScreenBufferMaterialId == -1 )
  3212. {
  3213. m_nFullScreenBufferMaterialId = CreateNewTextureID();
  3214. DrawSetTextureMaterial( m_nFullScreenBufferMaterialId, m_FullScreenBufferMaterial );
  3215. }
  3216. }
  3217. unsigned char oldColor[4];
  3218. oldColor[0] = m_DrawColor[0];
  3219. oldColor[1] = m_DrawColor[1];
  3220. oldColor[2] = m_DrawColor[2];
  3221. oldColor[3] = m_DrawColor[3];
  3222. DrawSetColor( 255, 255, 255, 255 );
  3223. DrawSetTexture( bIgnoreAlphaWhenCompositing ? m_nFullScreenBufferMaterialIgnoreAlphaId : m_nFullScreenBufferMaterialId );
  3224. float u0, u1, v0, v1;
  3225. GetFullScreenTexCoords( 0, 0, nOffscreenWidth, nOffscreenHeight, &u0, &v0, &u1, &v1 );
  3226. DrawTexturedSubRect( nLeft, nTop, nRight, nBottom, u0, v0, u1, v1 );
  3227. m_DrawColor[0] = oldColor[0];
  3228. m_DrawColor[1] = oldColor[1];
  3229. m_DrawColor[2] = oldColor[2];
  3230. m_DrawColor[3] = oldColor[3];
  3231. }
  3232. //-----------------------------------------------------------------------------
  3233. // Draws a rectangle, setting z to the current value
  3234. //-----------------------------------------------------------------------------
  3235. float CMatSystemSurface::GetZPos() const
  3236. {
  3237. return m_flZPos;
  3238. }
  3239. //-----------------------------------------------------------------------------
  3240. // Some drawing methods that cannot be accomplished under Win32
  3241. //-----------------------------------------------------------------------------
  3242. #define CIRCLE_POINTS 360
  3243. void CMatSystemSurface::DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a )
  3244. {
  3245. MAT_FUNC;
  3246. Assert( g_bInDrawing );
  3247. // Draw a circle
  3248. int iDegrees = 0;
  3249. Vector vecPoint, vecLastPoint(0,0,0);
  3250. vecPoint.z = 0.0f;
  3251. Color clr;
  3252. clr.SetColor( r, g, b, a );
  3253. DrawSetColor( clr );
  3254. for ( int i = 0; i < CIRCLE_POINTS; i++ )
  3255. {
  3256. float flRadians = DEG2RAD( iDegrees );
  3257. iDegrees += (360 / CIRCLE_POINTS);
  3258. float ca = cos( flRadians );
  3259. float sa = sin( flRadians );
  3260. // Rotate it around the circle
  3261. vecPoint.x = centerx + (radius * sa);
  3262. vecPoint.y = centery - (radius * ca);
  3263. // Draw the point, if it's not on the previous point, to avoid smaller circles being brighter
  3264. if ( vecLastPoint != vecPoint )
  3265. {
  3266. DrawFilledRect( vecPoint.x, vecPoint.y, vecPoint.x + 1, vecPoint.y + 1 );
  3267. }
  3268. vecLastPoint = vecPoint;
  3269. }
  3270. }
  3271. //-----------------------------------------------------------------------------
  3272. // Purpose: Draws colored text to a vgui panel
  3273. // Input : *font - font to use
  3274. // x - position of text
  3275. // y -
  3276. // r - color of text
  3277. // g -
  3278. // b -
  3279. // a - alpha ( 255 = opaque, 0 = transparent )
  3280. // *fmt - va_* text string
  3281. // ... -
  3282. // Output : int - horizontal # of pixels drawn
  3283. //-----------------------------------------------------------------------------
  3284. void CMatSystemSurface::DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, const char *fmt, va_list argptr )
  3285. {
  3286. Assert( g_bInDrawing );
  3287. int len;
  3288. char data[1024];
  3289. DrawSetTextPos( x, y );
  3290. DrawSetTextColor( r, g, b, a );
  3291. len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
  3292. CMatRenderContextPtr prc( g_pMaterialSystem );
  3293. DrawSetTextFont( font );
  3294. wchar_t szconverted[ 1024 ];
  3295. g_pVGuiLocalize->ConvertANSIToUnicode( data, szconverted, 1024 );
  3296. DrawPrintText( szconverted, wcslen(szconverted ) );
  3297. }
  3298. void CMatSystemSurface::DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, const char *fmt, ... )
  3299. {
  3300. va_list argptr;
  3301. va_start( argptr, fmt );
  3302. DrawColoredText( font, x, y, r, g, b, a, fmt, argptr );
  3303. va_end(argptr);
  3304. }
  3305. //-----------------------------------------------------------------------------
  3306. // Draws text with current font at position and wordwrapped to the rect using color values specified
  3307. //-----------------------------------------------------------------------------
  3308. void CMatSystemSurface::SearchForWordBreak( vgui::HFont font, char *text, int& chars, int& pixels )
  3309. {
  3310. chars = pixels = 0;
  3311. while ( 1 )
  3312. {
  3313. char ch = text[ chars ];
  3314. int a, b, c;
  3315. GetCharABCwide( font, ch, a, b, c );
  3316. if ( ch == 0 || ch <= 32 )
  3317. {
  3318. if ( ch == 32 && chars == 0 )
  3319. {
  3320. pixels += ( b + c );
  3321. chars++;
  3322. }
  3323. break;
  3324. }
  3325. pixels += ( b + c );
  3326. chars++;
  3327. }
  3328. }
  3329. //-----------------------------------------------------------------------------
  3330. // Purpose: If text width is specified, reterns height of text at that width
  3331. //-----------------------------------------------------------------------------
  3332. void CMatSystemSurface::DrawTextHeight( vgui::HFont font, int w, int& h, char *fmt, ... )
  3333. {
  3334. if ( !font )
  3335. return;
  3336. int len;
  3337. char data[8192];
  3338. va_list argptr;
  3339. va_start( argptr, fmt );
  3340. len = Q_vsnprintf( data, sizeof( data ), fmt, argptr );
  3341. va_end( argptr );
  3342. int x = 0;
  3343. int y = 0;
  3344. int ystep = GetFontTall( font );
  3345. int startx = x;
  3346. int endx = x + w;
  3347. //int endy = y + h;
  3348. int endy = 0;
  3349. int chars = 0;
  3350. int pixels = 0;
  3351. for ( int i = 0 ; i < len; i += chars )
  3352. {
  3353. SearchForWordBreak( font, &data[ i ], chars, pixels );
  3354. if ( data[ i ] == '\n' )
  3355. {
  3356. x = startx;
  3357. y += ystep;
  3358. chars = 1;
  3359. continue;
  3360. }
  3361. if ( x + ( pixels ) >= endx )
  3362. {
  3363. x = startx;
  3364. // No room even on new line!!!
  3365. if ( x + pixels >= endx )
  3366. break;
  3367. y += ystep;
  3368. }
  3369. for ( int j = 0 ; j < chars; j++ )
  3370. {
  3371. int a, b, c;
  3372. char ch = data[ i + j ];
  3373. GetCharABCwide( font, ch, a, b, c );
  3374. x += a + b + c;
  3375. }
  3376. }
  3377. endy = y+ystep;
  3378. h = endy;
  3379. }
  3380. //-----------------------------------------------------------------------------
  3381. // Draws text with current font at position and wordwrapped to the rect using color values specified
  3382. //-----------------------------------------------------------------------------
  3383. void CMatSystemSurface::DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, const char *fmt, ... )
  3384. {
  3385. MAT_FUNC;
  3386. Assert( g_bInDrawing );
  3387. if ( !font )
  3388. return;
  3389. int len;
  3390. char data[8192];
  3391. va_list argptr;
  3392. va_start( argptr, fmt );
  3393. len = Q_vsnprintf( data, sizeof( data ), fmt, argptr );
  3394. va_end( argptr );
  3395. DrawSetTextPos( x, y );
  3396. DrawSetTextColor( r, g, b, a );
  3397. DrawSetTextFont( font );
  3398. int ystep = GetFontTall( font );
  3399. int startx = x;
  3400. int endx = x + w;
  3401. int endy = y + h;
  3402. int chars = 0;
  3403. int pixels = 0;
  3404. char word[ 512 ];
  3405. char space[ 2 ];
  3406. space[1] = 0;
  3407. space[0] = ' ';
  3408. for ( int i = 0 ; i < len; i += chars )
  3409. {
  3410. SearchForWordBreak( font, &data[ i ], chars, pixels );
  3411. if ( data[ i ] == '\n' )
  3412. {
  3413. x = startx;
  3414. y += ystep;
  3415. chars = 1;
  3416. continue;
  3417. }
  3418. if ( x + ( pixels ) >= endx )
  3419. {
  3420. x = startx;
  3421. // No room even on new line!!!
  3422. if ( x + pixels >= endx )
  3423. break;
  3424. y += ystep;
  3425. }
  3426. if ( y + ystep >= endy )
  3427. break;
  3428. if ( chars <= 0 )
  3429. continue;
  3430. Q_strncpy( word, &data[ i ], chars + 1 );
  3431. DrawSetTextPos( x, y );
  3432. wchar_t szconverted[ 1024 ];
  3433. g_pVGuiLocalize->ConvertANSIToUnicode( word, szconverted, 1024 );
  3434. DrawPrintText( szconverted, wcslen(szconverted ) );
  3435. // Leave room for space, too
  3436. x += DrawTextLen( font, word );
  3437. }
  3438. }
  3439. //-----------------------------------------------------------------------------
  3440. // Purpose: Determine length of text string
  3441. //-----------------------------------------------------------------------------
  3442. int CMatSystemSurface::DrawTextLen( vgui::HFont font, const char *fmt, ... )
  3443. {
  3444. va_list argptr;
  3445. char data[1024];
  3446. int len;
  3447. va_start(argptr, fmt);
  3448. len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
  3449. va_end(argptr);
  3450. int i;
  3451. int x = 0;
  3452. int a = 0, b = 0, c = 0;
  3453. for ( i = 0 ; i < len; i++ )
  3454. {
  3455. GetCharABCwide( font, data[i], a, b, c );
  3456. x += a + b + c;
  3457. }
  3458. return x;
  3459. }
  3460. //-----------------------------------------------------------------------------
  3461. // Disable clipping during rendering
  3462. //-----------------------------------------------------------------------------
  3463. void CMatSystemSurface::DisableClipping( bool bDisable )
  3464. {
  3465. EnableScissor( !bDisable );
  3466. }
  3467. //-----------------------------------------------------------------------------
  3468. // Purpose: unlocks the cursor state
  3469. //-----------------------------------------------------------------------------
  3470. bool CMatSystemSurface::IsCursorLocked() const
  3471. {
  3472. return ::IsCursorLocked();
  3473. }
  3474. //-----------------------------------------------------------------------------
  3475. // Sets the mouse Get + Set callbacks
  3476. //-----------------------------------------------------------------------------
  3477. void CMatSystemSurface::SetMouseCallbacks( GetMouseCallback_t GetFunc, SetMouseCallback_t SetFunc )
  3478. {
  3479. // FIXME: Remove! This is obsolete
  3480. Assert(0);
  3481. }
  3482. //-----------------------------------------------------------------------------
  3483. // Tells the surface to ignore windows messages
  3484. //-----------------------------------------------------------------------------
  3485. void CMatSystemSurface::EnableWindowsMessages( bool bEnable )
  3486. {
  3487. if ( m_bEnableInput == bEnable )
  3488. return;
  3489. if ( bEnable )
  3490. {
  3491. g_pInputSystem->AddUIEventListener();
  3492. }
  3493. else
  3494. {
  3495. g_pInputSystem->RemoveUIEventListener();
  3496. }
  3497. m_bEnableInput = bEnable;
  3498. }
  3499. void CMatSystemSurface::MovePopupToFront(VPANEL panel)
  3500. {
  3501. int index = m_PopupList.Find( panel );
  3502. if ( index == m_PopupList.InvalidIndex() )
  3503. return;
  3504. if ( index != m_PopupList.Count() - 1 )
  3505. {
  3506. m_PopupList.Remove( index );
  3507. m_PopupList.AddToTail( panel );
  3508. if ( g_bSpewFocus )
  3509. {
  3510. char const *pName;
  3511. pName = ipanel()->GetName( panel );
  3512. Msg( "%s moved to front\n", pName ? pName : "(no name)" );
  3513. }
  3514. }
  3515. // If the modal panel isn't a parent, restore it to the top, to prevent a hard lock
  3516. if ( input()->GetAppModalSurface() )
  3517. {
  3518. if ( !g_pVGuiPanel->HasParent(panel, input()->GetAppModalSurface()) )
  3519. {
  3520. VPANEL p = input()->GetAppModalSurface();
  3521. index = m_PopupList.Find( p );
  3522. if ( index != m_PopupList.InvalidIndex() )
  3523. {
  3524. m_PopupList.Remove( index );
  3525. m_PopupList.AddToTail( p );
  3526. }
  3527. }
  3528. }
  3529. ivgui()->PostMessage(panel, new KeyValues("OnMovedPopupToFront"), NULL);
  3530. }
  3531. void CMatSystemSurface::MovePopupToBack(VPANEL panel)
  3532. {
  3533. int index = m_PopupList.Find( panel );
  3534. if ( index == m_PopupList.InvalidIndex() )
  3535. {
  3536. return;
  3537. }
  3538. m_PopupList.Remove( index );
  3539. m_PopupList.AddToHead( panel );
  3540. }
  3541. bool CMatSystemSurface::IsInThink( VPANEL panel)
  3542. {
  3543. if ( m_bInThink )
  3544. {
  3545. if ( panel == m_CurrentThinkPanel ) // HasParent() returns true if you pass yourself in
  3546. {
  3547. return false;
  3548. }
  3549. return ipanel()->HasParent( panel, m_CurrentThinkPanel);
  3550. }
  3551. return false;
  3552. }
  3553. //-----------------------------------------------------------------------------
  3554. // Purpose:
  3555. //-----------------------------------------------------------------------------
  3556. bool CMatSystemSurface::IsCursorVisible()
  3557. {
  3558. return (_currentCursor != dc_none);
  3559. }
  3560. bool CMatSystemSurface::IsTextureIDValid(int id)
  3561. {
  3562. // FIXME:
  3563. return true;
  3564. }
  3565. void CMatSystemSurface::SetAllowHTMLJavaScript( bool state )
  3566. {
  3567. m_bAllowJavaScript = state;
  3568. }
  3569. IHTML *CMatSystemSurface::CreateHTMLWindow(vgui::IHTMLEvents *events,VPANEL context)
  3570. {
  3571. #if defined( ENABLE_HTMLWINDOW )
  3572. HtmlWindow *IE = new HtmlWindow(events,context,reinterpret_cast<HWND>( GetAttachedWindow() ), m_bAllowJavaScript, false);
  3573. IE->Show(false);
  3574. _htmlWindows.AddToTail(IE);
  3575. return dynamic_cast<IHTML *>(IE);
  3576. #else
  3577. Assert( 0 );
  3578. return NULL;
  3579. #endif
  3580. }
  3581. void CMatSystemSurface::DeleteHTMLWindow(IHTML *htmlwin)
  3582. {
  3583. #if defined( ENABLE_HTMLWINDOW )
  3584. HtmlWindow *IE =static_cast<HtmlWindow *>(htmlwin);
  3585. if(IE)
  3586. {
  3587. _htmlWindows.FindAndRemove( IE );
  3588. delete IE;
  3589. }
  3590. #elif !defined( _X360 ) && !defined( _PS3 )
  3591. //#error "GameUI now NEEDS the HTML component!!"
  3592. #endif
  3593. }
  3594. void CMatSystemSurface::PaintHTMLWindow(IHTML *htmlwin)
  3595. {
  3596. #if defined( ENABLE_HTMLWINDOW )
  3597. HtmlWindow *IE = static_cast<HtmlWindow *>(htmlwin);
  3598. if(IE)
  3599. {
  3600. //HBITMAP bits;
  3601. HDC hdc = ::GetDC(reinterpret_cast<HWND>( GetAttachedWindow() ));
  3602. IE->OnPaint(hdc);
  3603. ::ReleaseDC( reinterpret_cast<HWND>( GetAttachedWindow() ), hdc );
  3604. }
  3605. #endif
  3606. }
  3607. bool CMatSystemSurface::BHTMLWindowNeedsPaint(IHTML *htmlwin)
  3608. {
  3609. return false;
  3610. }
  3611. //-----------------------------------------------------------------------------
  3612. /*void CMatSystemSurface::DrawSetTextureRGBA( int id, const unsigned char* rgba, int wide, int tall )
  3613. {
  3614. TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, IMAGE_FORMAT_RGBA8888 );
  3615. }*/
  3616. void CMatSystemSurface::DrawSetTextureRGBA( int id, const unsigned char* rgba, int wide, int tall )
  3617. {
  3618. TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, IMAGE_FORMAT_RGBA8888, k_ETextureScalingPointSample );
  3619. }
  3620. void CMatSystemSurface::DrawSetTextureRGBALinear( int id, const unsigned char *rgba, int wide, int tall )
  3621. {
  3622. TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, IMAGE_FORMAT_RGBA8888, k_ETextureScalingLinear );
  3623. }
  3624. void CMatSystemSurface::DrawSetTextureRGBAEx( int id, const unsigned char* rgba, int wide, int tall, ImageFormat format )
  3625. {
  3626. TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, format, k_ETextureScalingPointSample );
  3627. }
  3628. void CMatSystemSurface::DrawSetSubTextureRGBA( int textureID, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
  3629. {
  3630. TextureDictionary()->SetSubTextureRGBA( textureID, drawX, drawY, rgba, subTextureWide, subTextureTall );
  3631. }
  3632. #if defined( _X360 )
  3633. //-----------------------------------------------------------------------------
  3634. // Purpose: Get the texture id for the local gamerpic.
  3635. //-----------------------------------------------------------------------------
  3636. int CMatSystemSurface::GetLocalGamerpicTextureID( void )
  3637. {
  3638. return TextureDictionary()->GetLocalGamerpicTextureID();
  3639. }
  3640. //-----------------------------------------------------------------------------
  3641. // Purpose: Update the local gamerpic texture. Use the given texture if a gamerpic cannot be loaded.
  3642. //-----------------------------------------------------------------------------
  3643. bool CMatSystemSurface::SetLocalGamerpicTexture( DWORD userIndex, const char *pDefaultGamerpicFileName )
  3644. {
  3645. return TextureDictionary()->SetLocalGamerpicTexture( userIndex, pDefaultGamerpicFileName );
  3646. }
  3647. //-----------------------------------------------------------------------------
  3648. // Purpose: Set the current texture to be the local gamerpic.
  3649. //-----------------------------------------------------------------------------
  3650. bool CMatSystemSurface::DrawSetTextureLocalGamerpic( void )
  3651. {
  3652. int id = TextureDictionary()->GetLocalGamerpicTextureID();
  3653. if ( id != INVALID_TEXTURE_ID )
  3654. {
  3655. DrawSetTexture( id );
  3656. return true;
  3657. }
  3658. return false;
  3659. }
  3660. //-----------------------------------------------------------------------------
  3661. // Purpose: Get the texture id for a remote gamerpic with the given xuid.
  3662. //-----------------------------------------------------------------------------
  3663. int CMatSystemSurface::GetRemoteGamerpicTextureID( XUID xuid )
  3664. {
  3665. return TextureDictionary()->GetRemoteGamerpicTextureID( xuid );
  3666. }
  3667. //-----------------------------------------------------------------------------
  3668. // Purpose: Update the remote gamerpic texture for the given xuid.
  3669. // Use the given texture if a gamerpic cannot be loaded.
  3670. //-----------------------------------------------------------------------------
  3671. bool CMatSystemSurface::SetRemoteGamerpicTextureID( XUID xuid, const char *pDefaultGamerpicFileName )
  3672. {
  3673. return TextureDictionary()->SetRemoteGamerpicTextureID( xuid, pDefaultGamerpicFileName );
  3674. }
  3675. //-----------------------------------------------------------------------------
  3676. // Purpose: Set the current texture to be the remote player's gamerpic.
  3677. // Returns false if the remote gamerpic texture has not been set for the given xuid.
  3678. //-----------------------------------------------------------------------------
  3679. bool CMatSystemSurface::DrawSetTextureRemoteGamerpic( XUID xuid )
  3680. {
  3681. int id = TextureDictionary()->GetRemoteGamerpicTextureID( xuid );
  3682. if ( id != INVALID_TEXTURE_ID )
  3683. {
  3684. DrawSetTexture( id );
  3685. return true;
  3686. }
  3687. return false;
  3688. }
  3689. #endif // _X360
  3690. void CMatSystemSurface::DrawUpdateRegionTextureRGBA( int nTextureID, int x, int y, const unsigned char *pchData, int wide, int tall, ImageFormat imageFormat )
  3691. {
  3692. TextureDictionary()->UpdateSubTextureRGBA( nTextureID, x, y, pchData, wide, tall, imageFormat );
  3693. }
  3694. void CMatSystemSurface::SetModalPanel(VPANEL )
  3695. {
  3696. }
  3697. VPANEL CMatSystemSurface::GetModalPanel()
  3698. {
  3699. return 0;
  3700. }
  3701. void CMatSystemSurface::UnlockCursor()
  3702. {
  3703. ::LockCursor( GetInputContext(), false );
  3704. }
  3705. void CMatSystemSurface::LockCursor()
  3706. {
  3707. ::LockCursor( GetInputContext(), true );
  3708. }
  3709. void CMatSystemSurface::SetTranslateExtendedKeys(bool state)
  3710. {
  3711. }
  3712. VPANEL CMatSystemSurface::GetTopmostPopup()
  3713. {
  3714. return 0;
  3715. }
  3716. //-----------------------------------------------------------------------------
  3717. // Purpose: gets the absolute coordinates of the screen (in screen space)
  3718. //-----------------------------------------------------------------------------
  3719. void CMatSystemSurface::GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall)
  3720. {
  3721. // always work in full window screen space
  3722. x = 0;
  3723. y = 0;
  3724. GetScreenSize(wide, tall);
  3725. }
  3726. // returns true if the specified panel is a child of the current modal panel
  3727. // if no modal panel is set, then this always returns TRUE
  3728. static bool IsChildOfModalSubTree(VPANEL panel)
  3729. {
  3730. if ( !panel )
  3731. return true;
  3732. VPANEL modalSubTree = input()->GetModalSubTree();
  3733. if ( modalSubTree )
  3734. {
  3735. bool restrictMessages = input()->ShouldModalSubTreeReceiveMessages();
  3736. // If panel is child of modal subtree, the allow messages to route to it if restrict messages is set
  3737. bool isChildOfModal = ipanel()->HasParent( panel, modalSubTree );
  3738. if ( isChildOfModal )
  3739. {
  3740. return restrictMessages;
  3741. }
  3742. // If panel is not a child of modal subtree, then only allow messages if we're not restricting them to the modal subtree
  3743. else
  3744. {
  3745. return !restrictMessages;
  3746. }
  3747. }
  3748. return true;
  3749. }
  3750. void CMatSystemSurface::CalculateMouseVisible()
  3751. {
  3752. int i;
  3753. m_bNeedsMouse = false;
  3754. m_bNeedsKeyboard = false;
  3755. if ( input()->GetMouseCapture() != 0 )
  3756. return;
  3757. int c = surface()->GetPopupCount();
  3758. VPANEL modalSubTree = input()->GetModalSubTree();
  3759. if ( modalSubTree )
  3760. {
  3761. m_bNeedsMouse = input()->ShouldModalSubTreeShowMouse();
  3762. for (i = 0 ; i < c ; i++ )
  3763. {
  3764. VPanel *pop = (VPanel *)surface()->GetPopup(i) ;
  3765. bool isChildOfModalSubPanel = IsChildOfModalSubTree( (VPANEL)pop );
  3766. if ( !isChildOfModalSubPanel )
  3767. continue;
  3768. bool isVisible=pop->IsVisible();
  3769. VPanel *p= pop->GetParent();
  3770. while (p && isVisible)
  3771. {
  3772. if( p->IsVisible()==false)
  3773. {
  3774. isVisible=false;
  3775. break;
  3776. }
  3777. p=p->GetParent();
  3778. }
  3779. if ( isVisible )
  3780. {
  3781. m_bNeedsMouse = m_bNeedsMouse || pop->IsMouseInputEnabled();
  3782. m_bNeedsKeyboard = m_bNeedsKeyboard || pop->IsKeyBoardInputEnabled();
  3783. // Seen enough!!!
  3784. if ( m_bNeedsMouse && m_bNeedsKeyboard )
  3785. break;
  3786. }
  3787. }
  3788. }
  3789. else
  3790. {
  3791. for (i = 0 ; i < c ; i++ )
  3792. {
  3793. VPanel *pop = (VPanel *)surface()->GetPopup(i) ;
  3794. bool isVisible=pop->IsVisible();
  3795. VPanel *p= pop->GetParent();
  3796. while (p && isVisible)
  3797. {
  3798. if( p->IsVisible()==false)
  3799. {
  3800. isVisible=false;
  3801. break;
  3802. }
  3803. p=p->GetParent();
  3804. }
  3805. if ( isVisible )
  3806. {
  3807. m_bNeedsMouse = m_bNeedsMouse || pop->IsMouseInputEnabled();
  3808. m_bNeedsKeyboard = m_bNeedsKeyboard || pop->IsKeyBoardInputEnabled();
  3809. // Seen enough!!!
  3810. if ( m_bNeedsMouse && m_bNeedsKeyboard )
  3811. break;
  3812. }
  3813. }
  3814. }
  3815. // [jason] If we don't handle windows input event messages, ensure that we UnlockCursor:
  3816. // this is used so that in-game Scaleform can claim mouse focus on PC and have the mouse move around
  3817. #if defined( CSTRIKE15 )
  3818. if ( IsPC() && !m_bNeedsMouse )
  3819. {
  3820. m_bNeedsMouse = !m_bEnableInput;
  3821. }
  3822. #endif // defined( CSTRIKE15 )
  3823. if (m_bNeedsMouse)
  3824. {
  3825. g_pInputStackSystem->EnableInputContext( GetInputContext(), true );
  3826. // NOTE: We must unlock the cursor *before* the set call here.
  3827. // Failing to do this causes s_bCursorVisible to not be set correctly
  3828. // (UnlockCursor fails to set it correctly)
  3829. UnlockCursor();
  3830. if ( _currentCursor == vgui::dc_none )
  3831. {
  3832. SetCursor(vgui::dc_arrow);
  3833. }
  3834. }
  3835. else
  3836. {
  3837. g_pInputStackSystem->EnableInputContext( GetInputContext(), false );
  3838. SetCursor(vgui::dc_none);
  3839. LockCursor();
  3840. }
  3841. }
  3842. bool CMatSystemSurface::NeedKBInput()
  3843. {
  3844. return m_bNeedsKeyboard;
  3845. }
  3846. void CMatSystemSurface::SurfaceGetCursorPos(int &x, int &y)
  3847. {
  3848. GetCursorPos( x, y );
  3849. }
  3850. void CMatSystemSurface::SurfaceSetCursorPos(int x, int y)
  3851. {
  3852. SetCursorPos( x, y );
  3853. }
  3854. //-----------------------------------------------------------------------------
  3855. // Purpose: global alpha setting functions
  3856. //-----------------------------------------------------------------------------
  3857. void CMatSystemSurface::DrawSetAlphaMultiplier( float alpha /* [0..1] */ )
  3858. {
  3859. m_flAlphaMultiplier = clamp(alpha, 0.0f, 1.0f);
  3860. }
  3861. //-----------------------------------------------------------------------------
  3862. // Purpose: data accessor
  3863. //-----------------------------------------------------------------------------
  3864. float CMatSystemSurface::DrawGetAlphaMultiplier()
  3865. {
  3866. return m_flAlphaMultiplier;
  3867. }
  3868. //-----------------------------------------------------------------------------
  3869. // Purpose:
  3870. // Input : *curOrAniFile -
  3871. // Output : vgui::HCursor
  3872. //-----------------------------------------------------------------------------
  3873. vgui::HCursor CMatSystemSurface::CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
  3874. {
  3875. return Cursor_CreateCursorFromFile( curOrAniFile, pPathID );
  3876. }
  3877. void CMatSystemSurface::SetPanelForInput( VPANEL vpanel )
  3878. {
  3879. g_pIInput->AssociatePanelWithInputContext( DEFAULT_INPUT_CONTEXT, vpanel );
  3880. if ( vpanel )
  3881. {
  3882. m_bNeedsKeyboard = true;
  3883. }
  3884. else
  3885. {
  3886. m_bNeedsKeyboard = false;
  3887. }
  3888. }
  3889. #if defined( WIN32 ) && !defined( _X360 )
  3890. static bool GetIconSize( ICONINFO& iconInfo, int& w, int& h )
  3891. {
  3892. w = h = 0;
  3893. HBITMAP bitmap = iconInfo.hbmColor;
  3894. BITMAP bm;
  3895. if ( 0 == GetObject((HGDIOBJ)bitmap, sizeof(BITMAP), (LPVOID)&bm) )
  3896. {
  3897. return false;
  3898. }
  3899. w = bm.bmWidth;
  3900. h = bm.bmHeight;
  3901. return true;
  3902. }
  3903. // If rgba is NULL, bufsize gets filled in w/ # of bytes required
  3904. static bool GetIconBits( HDC hdc, ICONINFO& iconInfo, int& w, int& h, unsigned char *rgba, size_t& bufsize )
  3905. {
  3906. if ( !iconInfo.hbmColor || !iconInfo.hbmMask )
  3907. return false;
  3908. if ( !rgba )
  3909. {
  3910. if ( !GetIconSize( iconInfo, w, h ) )
  3911. return false;
  3912. bufsize = (size_t)( ( w * h ) << 2 );
  3913. return true;
  3914. }
  3915. bool bret = false;
  3916. Assert( w > 0 );
  3917. Assert( h > 0 );
  3918. Assert( bufsize == (size_t)( ( w * h ) << 2 ) );
  3919. DWORD *maskData = new DWORD[ w * h ];
  3920. DWORD *colorData = new DWORD[ w * h ];
  3921. DWORD *output = (DWORD *)rgba;
  3922. BITMAPINFO bmInfo;
  3923. memset( &bmInfo, 0, sizeof( bmInfo ) );
  3924. bmInfo.bmiHeader.biSize = sizeof( bmInfo.bmiHeader );
  3925. bmInfo.bmiHeader.biWidth = w;
  3926. bmInfo.bmiHeader.biHeight = h;
  3927. bmInfo.bmiHeader.biPlanes = 1;
  3928. bmInfo.bmiHeader.biBitCount = 32;
  3929. bmInfo.bmiHeader.biCompression = BI_RGB;
  3930. // Get the info about the bits
  3931. if ( GetDIBits( hdc, iconInfo.hbmMask, 0, h, maskData, &bmInfo, DIB_RGB_COLORS ) == h &&
  3932. GetDIBits( hdc, iconInfo.hbmColor, 0, h, colorData, &bmInfo, DIB_RGB_COLORS ) == h )
  3933. {
  3934. bret = true;
  3935. for ( int row = 0; row < h; ++row )
  3936. {
  3937. // Invert
  3938. int r = ( h - row - 1 );
  3939. int rowstart = r * w;
  3940. DWORD *color = &colorData[ rowstart ];
  3941. DWORD *mask = &maskData[ rowstart ];
  3942. DWORD *outdata = &output[ row * w ];
  3943. for ( int col = 0; col < w; ++col )
  3944. {
  3945. unsigned char *cr = ( unsigned char * )&color[ col ];
  3946. // Set alpha
  3947. cr[ 3 ] = mask[ col ] == 0 ? 0xff : 0x00;
  3948. // Swap blue and red
  3949. unsigned char t = cr[ 2 ];
  3950. cr[ 2 ] = cr[ 0 ];
  3951. cr[ 0 ] = t;
  3952. *( unsigned int *)&outdata[ col ] = *( unsigned int * )cr;
  3953. }
  3954. }
  3955. }
  3956. delete[] colorData;
  3957. delete[] maskData;
  3958. return bret;
  3959. }
  3960. static char const *g_pUniqueExtensions[]=
  3961. {
  3962. "exe",
  3963. "cur",
  3964. "ani",
  3965. };
  3966. static bool ShouldMakeUnique( char const *extension )
  3967. {
  3968. for ( int i = 0; i < ARRAYSIZE( g_pUniqueExtensions ); ++i )
  3969. {
  3970. if ( !Q_stricmp( extension, g_pUniqueExtensions[ i ] ) )
  3971. return true;
  3972. }
  3973. return false;
  3974. }
  3975. #endif // !_X360
  3976. vgui::IImage *CMatSystemSurface::GetIconImageForFullPath( char const *pFullPath )
  3977. {
  3978. vgui::IImage *newIcon = NULL;
  3979. #if defined( WIN32 ) && !defined( _X360 )
  3980. SHFILEINFO info = { 0 };
  3981. DWORD_PTR dwResult = SHGetFileInfo(
  3982. pFullPath,
  3983. 0,
  3984. &info,
  3985. sizeof( info ),
  3986. SHGFI_TYPENAME | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SHELLICONSIZE
  3987. );
  3988. if ( dwResult )
  3989. {
  3990. if ( info.szTypeName[ 0 ] != 0 )
  3991. {
  3992. char ext[ 32 ];
  3993. Q_ExtractFileExtension( pFullPath, ext, sizeof( ext ) );
  3994. char lookup[ 512 ];
  3995. Q_snprintf( lookup, sizeof( lookup ), "%s", ShouldMakeUnique( ext ) ? pFullPath : info.szTypeName );
  3996. // Now check the dictionary
  3997. unsigned short idx = m_FileTypeImages.Find( lookup );
  3998. if ( idx == m_FileTypeImages.InvalidIndex() )
  3999. {
  4000. ICONINFO iconInfo;
  4001. if ( 0 != GetIconInfo( info.hIcon, &iconInfo ) )
  4002. {
  4003. int w, h;
  4004. size_t bufsize = 0;
  4005. HDC hdc = ::GetDC(reinterpret_cast<HWND>( GetAttachedWindow() ));
  4006. if ( GetIconBits( hdc, iconInfo, w, h, NULL, bufsize ) )
  4007. {
  4008. byte *bits = new byte[ bufsize ];
  4009. if ( bits && GetIconBits( hdc, iconInfo, w, h, bits, bufsize ) )
  4010. {
  4011. newIcon = new MemoryBitmap( bits, w, h );
  4012. }
  4013. delete[] bits;
  4014. }
  4015. ::ReleaseDC( reinterpret_cast<HWND>( GetAttachedWindow() ), hdc );
  4016. }
  4017. idx = m_FileTypeImages.Insert( lookup, newIcon );
  4018. }
  4019. newIcon = m_FileTypeImages[ idx ];
  4020. }
  4021. DestroyIcon( info.hIcon );
  4022. }
  4023. #endif
  4024. return newIcon;
  4025. }
  4026. //-----------------------------------------------------------------------------
  4027. // Purpose:
  4028. //-----------------------------------------------------------------------------
  4029. void CMatSystemSurface::Set3DPaintTempRenderTarget( const char *pRenderTargetName )
  4030. {
  4031. MAT_FUNC;
  4032. Assert( !m_bUsingTempFullScreenBufferMaterial );
  4033. m_bUsingTempFullScreenBufferMaterial = true;
  4034. InitFullScreenBuffer( pRenderTargetName );
  4035. }
  4036. //-----------------------------------------------------------------------------
  4037. // Purpose:
  4038. //-----------------------------------------------------------------------------
  4039. void CMatSystemSurface::Reset3DPaintTempRenderTarget( void )
  4040. {
  4041. MAT_FUNC;
  4042. Assert( m_bUsingTempFullScreenBufferMaterial );
  4043. m_bUsingTempFullScreenBufferMaterial = false;
  4044. InitFullScreenBuffer( MODEL_PANEL_RT_NAME );
  4045. }
  4046. void CMatSystemSurface::SetAbsPosForContext( int id, int x, int y )
  4047. {
  4048. ContextAbsPos_t search;
  4049. search.id = id;
  4050. int idx = m_ContextAbsPos.Find( search );
  4051. if ( idx == m_ContextAbsPos.InvalidIndex() )
  4052. {
  4053. idx = m_ContextAbsPos.Insert( search );
  4054. }
  4055. ContextAbsPos_t &entry = m_ContextAbsPos[ idx ];
  4056. entry.m_nPos[ 0 ] = x;
  4057. entry.m_nPos[ 1 ] = y;
  4058. }
  4059. void CMatSystemSurface::GetAbsPosForContext( int id, int &x, int& y )
  4060. {
  4061. ContextAbsPos_t search;
  4062. search.id = id;
  4063. int idx = m_ContextAbsPos.Find( search );
  4064. if ( idx == m_ContextAbsPos.InvalidIndex() )
  4065. {
  4066. x = y = 0;
  4067. return;
  4068. }
  4069. const ContextAbsPos_t &entry = m_ContextAbsPos[ idx ];
  4070. x = entry.m_nPos[ 0 ];
  4071. y = entry.m_nPos[ 1 ];
  4072. }
  4073. int CMatSystemSurface::GetTextureNumFrames( int id )
  4074. {
  4075. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial( id );
  4076. if ( !pMaterial )
  4077. {
  4078. return 0;
  4079. }
  4080. return pMaterial->GetNumAnimationFrames();
  4081. }
  4082. void CMatSystemSurface::DrawSetTextureFrame( int id, int nFrame, unsigned int *pFrameCache )
  4083. {
  4084. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial( id );
  4085. if ( !pMaterial )
  4086. {
  4087. return;
  4088. }
  4089. int nTotalFrames = pMaterial->GetNumAnimationFrames();
  4090. if ( !nTotalFrames )
  4091. {
  4092. return;
  4093. }
  4094. IMaterialVar *pFrameVar = pMaterial->FindVarFast( "$frame", pFrameCache );
  4095. if ( pFrameVar )
  4096. {
  4097. pFrameVar->SetIntValue( nFrame % nTotalFrames );
  4098. }
  4099. }
  4100. void CMatSystemSurface::GetClipRect( int &x0, int &y0, int &x1, int &y1 )
  4101. {
  4102. if ( !m_PaintStateStack.Count() )
  4103. return;
  4104. PaintState_t &paintState = m_PaintStateStack.Tail();
  4105. x0 = paintState.m_iScissorLeft;
  4106. y0 = paintState.m_iScissorTop;
  4107. x1 = paintState.m_iScissorRight;
  4108. y1 = paintState.m_iScissorBottom;
  4109. }
  4110. void CMatSystemSurface::SetClipRect( int x0, int y0, int x1, int y1 )
  4111. {
  4112. if ( !m_PaintStateStack.Count() )
  4113. return;
  4114. PaintState_t &paintState = m_PaintStateStack.Tail();
  4115. paintState.m_iScissorLeft = x0;
  4116. paintState.m_iScissorTop = y0;
  4117. paintState.m_iScissorRight = x1;
  4118. paintState.m_iScissorBottom = y1;
  4119. SetupPaintState( paintState );
  4120. }
  4121. //-----------------------------------------------------------------------------
  4122. //
  4123. //-----------------------------------------------------------------------------
  4124. void CMatSystemSurface::SetLanguage( const char *pLanguage )
  4125. {
  4126. FontManager().SetLanguage( pLanguage );
  4127. }
  4128. //-----------------------------------------------------------------------------
  4129. //
  4130. //-----------------------------------------------------------------------------
  4131. const char *CMatSystemSurface::GetLanguage()
  4132. {
  4133. return FontManager().GetLanguage();
  4134. }
  4135. void CMatSystemSurface::DrawTexturedRectEx( DrawTexturedRectParms_t *pDrawParms )
  4136. {
  4137. Assert( g_bInDrawing );
  4138. Assert( !m_bIn3DPaintMode );
  4139. // Don't even bother drawing fully transparent junk
  4140. if ( m_DrawColor[3] == 0 )
  4141. return;
  4142. // scale incoming alpha
  4143. int alpha_ul = 255.0f * ( (float)m_DrawColor[3]/255.0f * (float)pDrawParms->alpha_ul/255.0f );
  4144. int alpha_ur = 255.0f * ( (float)m_DrawColor[3]/255.0f * (float)pDrawParms->alpha_ur/255.0f );
  4145. int alpha_lr = 255.0f * ( (float)m_DrawColor[3]/255.0f * (float)pDrawParms->alpha_lr/255.0f );
  4146. int alpha_ll = 255.0f * ( (float)m_DrawColor[3]/255.0f * (float)pDrawParms->alpha_ll/255.0f );
  4147. // Don't even bother drawing fully transparent junk
  4148. if ( alpha_ul == 0 && alpha_ur == 0 && alpha_lr == 0 && alpha_ll == 0 )
  4149. return;
  4150. float s0, t0, s1, t1;
  4151. TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
  4152. float ssize = s1 - s0;
  4153. float tsize = t1 - t0;
  4154. // Rescale tex values into range of s0 to s1 ,etc.
  4155. float texs0 = s0 + pDrawParms->s0 * ( ssize );
  4156. float texs1 = s0 + pDrawParms->s1 * ( ssize );
  4157. float text0 = t0 + pDrawParms->t0 * ( tsize );
  4158. float text1 = t0 + pDrawParms->t1 * ( tsize );
  4159. // rotate about center
  4160. float cx = ( pDrawParms->x0 + pDrawParms->x1 ) / 2.0f;
  4161. float cy = ( pDrawParms->y0 + pDrawParms->y1 ) / 2.0f;
  4162. IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial( m_iBoundTexture );
  4163. InternalSetMaterial( pMaterial );
  4164. if ( !m_pMesh )
  4165. return;
  4166. meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
  4167. // ul
  4168. Vector in, out;
  4169. in.x = pDrawParms->x0 - cx;
  4170. in.y = pDrawParms->y0 - cy;
  4171. in.z = 0;
  4172. VectorYawRotate( in, pDrawParms->angle, out );
  4173. out.x += cx + m_nTranslateX;
  4174. out.y += cy + m_nTranslateY;
  4175. meshBuilder.Position3f( out.x, out.y, m_flZPos );
  4176. meshBuilder.Color4ub( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha_ul );
  4177. meshBuilder.TexCoord2f( 0, texs0, text0 );
  4178. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  4179. // ur
  4180. in.x = pDrawParms->x1 - cx;
  4181. in.y = pDrawParms->y0 - cy;
  4182. VectorYawRotate( in, pDrawParms->angle, out );
  4183. out.x += cx + m_nTranslateX;
  4184. out.y += cy + m_nTranslateY;
  4185. meshBuilder.Position3f( out.x, out.y, m_flZPos );
  4186. meshBuilder.Color4ub( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha_ur );
  4187. meshBuilder.TexCoord2f( 0, texs1, text0 );
  4188. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  4189. // lr
  4190. in.x = pDrawParms->x1 - cx;
  4191. in.y = pDrawParms->y1 - cy;
  4192. VectorYawRotate( in, pDrawParms->angle, out );
  4193. out.x += cx + m_nTranslateX;
  4194. out.y += cy + m_nTranslateY;
  4195. meshBuilder.Position3f( out.x, out.y, m_flZPos );
  4196. meshBuilder.Color4ub( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha_lr );
  4197. meshBuilder.TexCoord2f( 0, texs1, text1 );
  4198. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  4199. // ll
  4200. in.x = pDrawParms->x0 - cx;
  4201. in.y = pDrawParms->y1 - cy;
  4202. VectorYawRotate( in, pDrawParms->angle, out );
  4203. out.x += cx + m_nTranslateX;
  4204. out.y += cy + m_nTranslateY;
  4205. meshBuilder.Position3f( out.x, out.y, m_flZPos );
  4206. meshBuilder.Color4ub( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha_ll );
  4207. meshBuilder.TexCoord2f( 0, texs0, text1 );
  4208. meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
  4209. meshBuilder.End();
  4210. m_pMesh->Draw();
  4211. }