Team Fortress 2 Source Code as on 22/4/2020
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.

4614 lines
130 KiB

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