summaryrefslogtreecommitdiff
path: root/vguimatsurface
diff options
context:
space:
mode:
authorFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
committerFluorescentCIAAfricanAmerican <[email protected]>2020-04-22 12:56:21 -0400
commit3bf9df6b2785fa6d951086978a3e66f49427166a (patch)
tree2c0f1f0c63c4832882bc93814ebd2c2b1c6224e5 /vguimatsurface
downloadarchived-source-engine-2018-hl2-src-master.tar.xz
archived-source-engine-2018-hl2-src-master.zip
Diffstat (limited to 'vguimatsurface')
-rw-r--r--vguimatsurface/Clip2D.cpp457
-rw-r--r--vguimatsurface/Clip2D.h46
-rw-r--r--vguimatsurface/Cursor.cpp565
-rw-r--r--vguimatsurface/Cursor.h75
-rw-r--r--vguimatsurface/FontTextureCache.cpp512
-rw-r--r--vguimatsurface/FontTextureCache.h102
-rw-r--r--vguimatsurface/Input.cpp524
-rw-r--r--vguimatsurface/Input.h47
-rw-r--r--vguimatsurface/MatSystemSurface.cpp4614
-rw-r--r--vguimatsurface/MatSystemSurface.h643
-rw-r--r--vguimatsurface/TextureDictionary.cpp991
-rw-r--r--vguimatsurface/TextureDictionary.h63
-rw-r--r--vguimatsurface/memorybitmap.cpp181
-rw-r--r--vguimatsurface/memorybitmap.h63
-rw-r--r--vguimatsurface/vguimatsurface.h30
-rw-r--r--vguimatsurface/vguimatsurface.vpc104
-rw-r--r--vguimatsurface/xbox/xbox.def3
17 files changed, 9020 insertions, 0 deletions
diff --git a/vguimatsurface/Clip2D.cpp b/vguimatsurface/Clip2D.cpp
new file mode 100644
index 0000000..af4cef2
--- /dev/null
+++ b/vguimatsurface/Clip2D.cpp
@@ -0,0 +1,457 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains 2D clipping routines
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#include <vgui/ISurface.h>
+#include "Clip2D.h"
+#include "tier0/dbg.h"
+#include "utlvector.h"
+#if defined( _X360 )
+#include "materialsystem/imaterialsystem.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+//-----------------------------------------------------------------------------
+// Stretch texture to fit window ( before scissoring )
+//-----------------------------------------------------------------------------
+static bool g_bStretchTexture = false;
+
+
+//-----------------------------------------------------------------------------
+// Max # of vertices for clipping
+//-----------------------------------------------------------------------------
+enum
+{
+ VGUI_VERTEX_TEMP_COUNT = 48,
+};
+
+//-----------------------------------------------------------------------------
+// For simulated scissor tests...
+//-----------------------------------------------------------------------------
+struct ScissorRect_t
+{
+ int left;
+ int top;
+ int right;
+ int bottom;
+};
+
+static ScissorRect_t g_ScissorRect;
+static bool g_bScissor = false;
+static bool g_bFullScreenScissor = false;
+
+//-----------------------------------------------------------------------------
+// Enable/disable scissoring...
+//-----------------------------------------------------------------------------
+void EnableScissor( bool enable )
+{
+ g_bScissor = enable;
+}
+
+
+void SetScissorRect( int left, int top, int right, int bottom )
+{
+ // Check for a valid rectangle...
+ Assert( left <= right );
+ Assert( top <= bottom );
+
+ if ( g_ScissorRect.left == left && g_ScissorRect.right == right &&
+ g_ScissorRect.top == top && g_ScissorRect.bottom == bottom )
+ return;
+
+ g_ScissorRect.left = left;
+ g_ScissorRect.top = top;
+ g_ScissorRect.right = right;
+ g_ScissorRect.bottom = bottom;
+
+#if defined( _X360 )
+ // no reason to waste cpu on full screen scissor, gpu does it
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ int vx, vy, vw, vh;
+ pRenderContext->GetViewport( vx, vy, vw, vh );
+ g_bFullScreenScissor = (left <= vx && top <= vy && right >= vw && bottom >= vh );
+#endif
+}
+
+void GetScissorRect( int &left, int &top, int &right, int &bottom, bool &enabled )
+{
+ left = g_ScissorRect.left;
+ top = g_ScissorRect.top;
+ right = g_ScissorRect.right;
+ bottom = g_ScissorRect.bottom;
+ enabled = g_bScissor;
+}
+
+
+//-----------------------------------------------------------------------------
+// Used to clip the shadow decals
+//-----------------------------------------------------------------------------
+struct PolygonClipState_t
+{
+ int m_CurrVert;
+ int m_TempCount;
+ int m_ClipCount;
+ vgui::Vertex_t m_pTempVertices[VGUI_VERTEX_TEMP_COUNT];
+ vgui::Vertex_t* m_ppClipVertices[2][VGUI_VERTEX_TEMP_COUNT];
+};
+
+
+//-----------------------------------------------------------------------------
+// Clipping methods for 2D
+//-----------------------------------------------------------------------------
+class CClipTop
+{
+public:
+ static inline bool Inside( vgui::Vertex_t const& vert )
+ {
+ return vert.m_Position.y >= g_ScissorRect.top;
+ }
+ static inline float Clip( const Vector2D& one, const Vector2D& two )
+ {
+ return (g_ScissorRect.top - one.y) / (two.y - one.y);
+ }
+};
+
+class CClipLeft
+{
+public:
+ static inline bool Inside( vgui::Vertex_t const& vert )
+ {
+ return vert.m_Position.x >= g_ScissorRect.left;
+ }
+ static inline float Clip( const Vector2D& one, const Vector2D& two )
+ {
+ return (one.x - g_ScissorRect.left) / (one.x - two.x);
+ }
+};
+
+class CClipRight
+{
+public:
+ static inline bool Inside( vgui::Vertex_t const& vert )
+ {
+ return vert.m_Position.x < g_ScissorRect.right;
+ }
+ static inline float Clip( const Vector2D& one, const Vector2D& two )
+ {
+ return (g_ScissorRect.right - one.x) / (two.x - one.x);
+ }
+};
+
+class CClipBottom
+{
+public:
+ static inline bool Inside( vgui::Vertex_t const& vert )
+ {
+ return vert.m_Position.y < g_ScissorRect.bottom;
+ }
+ static inline float Clip( const Vector2D& one, const Vector2D& two )
+ {
+ return (one.y - g_ScissorRect.bottom) / (one.y - two.y);
+ }
+};
+
+template <class Clipper>
+static inline void Intersect( const vgui::Vertex_t& start, const vgui::Vertex_t& end, vgui::Vertex_t* pOut, Clipper& clipper )
+{
+ // Clip to the scissor rectangle
+ float t = Clipper::Clip( start.m_Position, end.m_Position );
+ Vector2DLerp( start.m_Position, end.m_Position, t, pOut->m_Position );
+ Vector2DLerp( start.m_TexCoord, end.m_TexCoord, t, pOut->m_TexCoord );
+}
+
+
+//-----------------------------------------------------------------------------
+// Clips a line segment to a single plane
+//-----------------------------------------------------------------------------
+template< class Clipper >
+bool ClipLineToPlane( Clipper &clipper, const vgui::Vertex_t *pInVerts, vgui::Vertex_t* pOutVerts )
+{
+ bool startInside = Clipper::Inside( pInVerts[0] );
+ bool endInside = Clipper::Inside( pInVerts[1] );
+
+ // Cull
+ if (!startInside && !endInside)
+ return false;
+
+ if (startInside && endInside)
+ {
+ pOutVerts[0] = pInVerts[0];
+ pOutVerts[1] = pInVerts[1];
+ }
+ else
+ {
+ int inIndex = startInside ? 0 : 1;
+ pOutVerts[inIndex] = pInVerts[inIndex];
+ Intersect( pInVerts[0], pInVerts[1], &pOutVerts[1 - inIndex], clipper );
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Clips a line segment to the current scissor rectangle
+//-----------------------------------------------------------------------------
+bool ClipLine( const vgui::Vertex_t *pInVerts, vgui::Vertex_t* pOutVerts )
+{
+ if ( g_bScissor && !g_bFullScreenScissor )
+ {
+ // Clippers...
+ CClipTop top;
+ CClipBottom bottom;
+ CClipLeft left;
+ CClipRight right;
+
+ // Sutherland-hodgman clip, not particularly efficient but that's ok for now
+ vgui::Vertex_t tempVerts[2];
+ if (!ClipLineToPlane( top, pInVerts, tempVerts ))
+ return false;
+ if (!ClipLineToPlane( bottom, tempVerts, pOutVerts ))
+ return false;
+ if (!ClipLineToPlane( left, pOutVerts, tempVerts ))
+ return false;
+ if (!ClipLineToPlane( right, tempVerts, pOutVerts ))
+ return false;
+
+ return true;
+ }
+ else
+ {
+ pOutVerts[0] = pInVerts[0];
+ pOutVerts[1] = pInVerts[1];
+ return true;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Methods associated with clipping 2D polygons
+//-----------------------------------------------------------------------------
+struct ScreenClipState_t
+{
+ int m_iCurrVert;
+ int m_iTempCount;
+ int m_iClipCount;
+ CUtlVector<vgui::Vertex_t> m_pTempVertices;
+ CUtlVector<vgui::Vertex_t*> m_ppClipVertices[2];
+};
+
+
+template <class Clipper>
+static void ScreenClip( ScreenClipState_t& clip, Clipper& clipper )
+{
+ if (clip.m_iClipCount < 3)
+ return;
+
+ // Ye Olde Sutherland-Hodgman clipping algorithm
+ int numOutVerts = 0;
+ vgui::Vertex_t** pSrcVert = clip.m_ppClipVertices[clip.m_iCurrVert].Base();
+ vgui::Vertex_t** pDestVert = clip.m_ppClipVertices[!clip.m_iCurrVert].Base();
+
+ int numVerts = clip.m_iClipCount;
+ vgui::Vertex_t* pStart = pSrcVert[numVerts-1];
+ bool startInside = Clipper::Inside( *pStart );
+ for (int i = 0; i < numVerts; ++i)
+ {
+ vgui::Vertex_t* pEnd = pSrcVert[i];
+ bool endInside = Clipper::Inside( *pEnd );
+ if (endInside)
+ {
+ if (!startInside)
+ {
+ // Started outside, ended inside, need to clip the edge
+ Assert( clip.m_iTempCount <= clip.m_pTempVertices.Count() );
+
+ // Allocate a new clipped vertex
+ pDestVert[numOutVerts] = &clip.m_pTempVertices[clip.m_iTempCount++];
+
+ // Clip the edge to the clip plane
+ Intersect( *pStart, *pEnd, pDestVert[numOutVerts], clipper );
+ ++numOutVerts;
+ }
+ pDestVert[numOutVerts++] = pEnd;
+ }
+ else
+ {
+ if (startInside)
+ {
+ // Started inside, ended outside, need to clip the edge
+ Assert( clip.m_iTempCount <= clip.m_pTempVertices.Count() );
+
+ // Allocate a new clipped vertex
+ pDestVert[numOutVerts] = &clip.m_pTempVertices[clip.m_iTempCount++];
+
+ // Clip the edge to the clip plane
+ Intersect( *pStart, *pEnd, pDestVert[numOutVerts], clipper );
+ ++numOutVerts;
+ }
+ }
+ pStart = pEnd;
+ startInside = endInside;
+ }
+
+ // Switch source lists
+ clip.m_iCurrVert = 1 - clip.m_iCurrVert;
+ clip.m_iClipCount = numOutVerts;
+}
+
+
+//-----------------------------------------------------------------------------
+// Clips a polygon to the screen area
+//-----------------------------------------------------------------------------
+int ClipPolygon( int iCount, vgui::Vertex_t *pVerts, int iTranslateX, int iTranslateY, vgui::Vertex_t ***pppOutVertex )
+{
+ static ScreenClipState_t clip;
+
+ // Allocate enough room in the clip state...
+ // Having no reallocations during clipping
+ clip.m_pTempVertices.EnsureCount( iCount * 4 );
+ clip.m_ppClipVertices[0].EnsureCount( iCount * 4 );
+ clip.m_ppClipVertices[1].EnsureCount( iCount * 4 );
+
+ // Copy the initial verts in...
+ for (int i = 0; i < iCount; ++i)
+ {
+ // NOTE: This only works because we EnsuredCount above
+ clip.m_pTempVertices[i] = pVerts[i];
+ clip.m_pTempVertices[i].m_Position.x += iTranslateX;
+ clip.m_pTempVertices[i].m_Position.y += iTranslateY;
+ clip.m_ppClipVertices[0][i] = &clip.m_pTempVertices[i];
+ }
+
+ if ( !g_bScissor || g_bFullScreenScissor )
+ {
+ Assert(pppOutVertex);
+ *pppOutVertex = clip.m_ppClipVertices[0].Base();
+ return iCount;
+ }
+
+ clip.m_iClipCount = iCount;
+ clip.m_iTempCount = iCount;
+ clip.m_iCurrVert = 0;
+
+ // Clippers...
+ CClipTop top;
+ CClipBottom bottom;
+ CClipLeft left;
+ CClipRight right;
+
+ // Sutherland-hodgman clip
+ ScreenClip( clip, top );
+ ScreenClip( clip, bottom );
+ ScreenClip( clip, left );
+ ScreenClip( clip, right );
+
+ if (clip.m_iClipCount < 3)
+ return 0;
+
+ // Return a pointer to the array of clipped vertices...
+ Assert(pppOutVertex);
+ *pppOutVertex = clip.m_ppClipVertices[clip.m_iCurrVert].Base();
+ return clip.m_iClipCount;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Used for clipping, produces an interpolated texture coordinate
+//-----------------------------------------------------------------------------
+inline float InterpTCoord(float val, float mins, float maxs, float tMin, float tMax)
+{
+ float flPercent;
+ if (mins != maxs)
+ flPercent = (float)(val - mins) / (maxs - mins);
+ else
+ flPercent = 0.5f;
+ return tMin + (tMax - tMin) * flPercent;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Does a scissor clip of the input rectangle.
+// Returns false if it is completely clipped off.
+//-----------------------------------------------------------------------------
+bool ClipRect( const vgui::Vertex_t &inUL, const vgui::Vertex_t &inLR,
+ vgui::Vertex_t *pOutUL, vgui::Vertex_t *pOutLR )
+{
+ // Check for a valid rectangle...
+// Assert( inUL.m_Position.x <= inLR.m_Position.x );
+// Assert( inUL.m_Position.y <= inLR.m_Position.y );
+
+ if ( IsX360() && ( !g_bScissor || g_bFullScreenScissor ||
+ ( inUL.m_Position.x >= g_ScissorRect.left && inLR.m_Position.x <= g_ScissorRect.right && inUL.m_Position.y >= g_ScissorRect.top && inLR.m_Position.y <= g_ScissorRect.bottom ) ) )
+ {
+ // clipping is not needed
+ // either full screen, and hw will do it or rect is inscribed, and operation is meaningless
+ *pOutUL = inUL;
+ *pOutLR = inLR;
+ return true;
+ }
+
+ if ( g_bScissor )
+ {
+ // Pick whichever left side is larger
+ if (g_ScissorRect.left > inUL.m_Position.x)
+ pOutUL->m_Position.x = g_ScissorRect.left;
+ else
+ pOutUL->m_Position.x = inUL.m_Position.x;
+
+ // Pick whichever right side is smaller
+ if (g_ScissorRect.right <= inLR.m_Position.x)
+ pOutLR->m_Position.x = g_ScissorRect.right;
+ else
+ pOutLR->m_Position.x = inLR.m_Position.x;
+
+ // Pick whichever top side is larger
+ if (g_ScissorRect.top > inUL.m_Position.y)
+ pOutUL->m_Position.y = g_ScissorRect.top;
+ else
+ pOutUL->m_Position.y = inUL.m_Position.y;
+
+ // Pick whichever bottom side is smaller
+ if (g_ScissorRect.bottom <= inLR.m_Position.y)
+ pOutLR->m_Position.y = g_ScissorRect.bottom;
+ else
+ pOutLR->m_Position.y = inLR.m_Position.y;
+
+ // Check for non-intersecting
+ if ( (pOutUL->m_Position.x > pOutLR->m_Position.x) ||
+ (pOutUL->m_Position.y > pOutLR->m_Position.y) )
+ {
+ return false;
+ }
+
+ if ( !g_bStretchTexture )
+ {
+ pOutUL->m_TexCoord.x = InterpTCoord(pOutUL->m_Position.x,
+ inUL.m_Position.x, inLR.m_Position.x, inUL.m_TexCoord.x, inLR.m_TexCoord.x);
+ pOutLR->m_TexCoord.x = InterpTCoord(pOutLR->m_Position.x,
+ inUL.m_Position.x, inLR.m_Position.x, inUL.m_TexCoord.x, inLR.m_TexCoord.x);
+
+ pOutUL->m_TexCoord.y = InterpTCoord(pOutUL->m_Position.y,
+ inUL.m_Position.y, inLR.m_Position.y, inUL.m_TexCoord.y, inLR.m_TexCoord.y);
+ pOutLR->m_TexCoord.y = InterpTCoord(pOutLR->m_Position.y,
+ inUL.m_Position.y, inLR.m_Position.y, inUL.m_TexCoord.y, inLR.m_TexCoord.y);
+ }
+ else
+ {
+ // FIXME, this isn't right
+ pOutUL->m_TexCoord = inUL.m_TexCoord;
+ pOutLR->m_TexCoord = inLR.m_TexCoord;
+ }
+ }
+ else
+ {
+ *pOutUL = inUL;
+ *pOutLR = inLR;
+ }
+
+ return true;
+}
+
diff --git a/vguimatsurface/Clip2D.h b/vguimatsurface/Clip2D.h
new file mode 100644
index 0000000..b196920
--- /dev/null
+++ b/vguimatsurface/Clip2D.h
@@ -0,0 +1,46 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains 2D clipping routines
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef CLIP2D_H
+#define CLIP2D_H
+
+namespace vgui
+{
+ struct Vertex_t;
+}
+
+//-----------------------------------------------------------------------------
+// Enable/disable scissoring...
+//-----------------------------------------------------------------------------
+void EnableScissor( bool enable );
+
+//-----------------------------------------------------------------------------
+// For simulated scissor tests...
+//-----------------------------------------------------------------------------
+void SetScissorRect( int left, int top, int right, int bottom );
+void GetScissorRect( int &left, int &top, int &right, int &bottom, bool &enabled );
+
+//-----------------------------------------------------------------------------
+// Clips a line segment to the current scissor rectangle
+//-----------------------------------------------------------------------------
+bool ClipLine( const vgui::Vertex_t *pInVerts, vgui::Vertex_t* pOutVerts );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Does a scissor clip of the input rectangle.
+// Returns false if it is completely clipped off.
+//-----------------------------------------------------------------------------
+bool ClipRect( const vgui::Vertex_t &inUL, const vgui::Vertex_t &inLR,
+ vgui::Vertex_t *pOutUL, vgui::Vertex_t *pOutLR );
+
+//-----------------------------------------------------------------------------
+// Clips a polygon to the screen area
+//-----------------------------------------------------------------------------
+int ClipPolygon( int iCount, vgui::Vertex_t *pVerts, int iTranslateX, int iTranslateY, vgui::Vertex_t ***pppOutVertex );
+
+#endif // CLIP2D_H \ No newline at end of file
diff --git a/vguimatsurface/Cursor.cpp b/vguimatsurface/Cursor.cpp
new file mode 100644
index 0000000..5451541
--- /dev/null
+++ b/vguimatsurface/Cursor.cpp
@@ -0,0 +1,565 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Methods associated with the cursor
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#if !defined( _X360 )
+ #define OEMRESOURCE //for OCR_* cursor junk
+ #include "winlite.h"
+#endif
+#include <appframework/ilaunchermgr.h>
+
+#if defined( USE_SDL )
+#undef M_PI
+#include "SDL.h"
+#endif
+
+#include "tier0/dbg.h"
+#include "tier0/vcrmode.h"
+#include "tier0/icommandline.h"
+#include "tier1/utldict.h"
+#include "Cursor.h"
+#include "vguimatsurface.h"
+#include "MatSystemSurface.h"
+#include "filesystem.h"
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#endif
+
+#if defined( USE_SDL )
+#include "materialsystem/imaterialsystem.h"
+#endif
+
+#include "inputsystem/iinputsystem.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+#if defined( USE_SDL )
+static SDL_Cursor *s_pDefaultCursor[ dc_last ];
+static SDL_Cursor *s_hCurrentCursor = NULL;
+static SDL_Cursor *s_hCurrentlySetCursor = NULL;
+#elif defined( WIN32 )
+static HICON s_pDefaultCursor[ dc_last ];
+static HICON s_hCurrentCursor = NULL;
+#endif
+static bool s_bCursorLocked = false;
+static bool s_bCursorVisible = true;
+static int s_nForceCursorVisibleCount = 0;
+static bool s_bSoftwareCursorActive = false;
+static int s_nSoftwareCursorTexture = -1;
+static float s_fSoftwareCursorOffsetX = 0;
+static float s_fSoftwareCursorOffsetY = 0;
+static int s_rnSoftwareCursorID[20];
+static float s_rfSoftwareCursorOffset[20][2];
+static bool s_bSoftwareCursorsInitialized = false;
+
+extern CMatSystemSurface g_MatSystemSurface;
+
+//-----------------------------------------------------------------------------
+// Initializes cursors
+//-----------------------------------------------------------------------------
+void InitCursors()
+{
+ // load up all default cursors
+#if defined( USE_SDL )
+
+ s_pDefaultCursor[ dc_none ] = NULL;
+ s_pDefaultCursor[ dc_arrow ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_ARROW );
+ s_pDefaultCursor[ dc_ibeam ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_IBEAM );
+ s_pDefaultCursor[ dc_hourglass ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_WAIT );
+ s_pDefaultCursor[ dc_crosshair ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_CROSSHAIR );
+ s_pDefaultCursor[ dc_waitarrow ]= SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_WAITARROW );
+ s_pDefaultCursor[ dc_sizenwse ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENWSE );
+ s_pDefaultCursor[ dc_sizenesw ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENESW );
+ s_pDefaultCursor[ dc_sizewe ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEWE );
+ s_pDefaultCursor[ dc_sizens ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZENS );
+ s_pDefaultCursor[ dc_sizeall ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_SIZEALL );
+ s_pDefaultCursor[ dc_no ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_NO );
+ s_pDefaultCursor[ dc_hand ] = SDL_CreateSystemCursor( SDL_SYSTEM_CURSOR_HAND );
+
+ s_hCurrentCursor = s_pDefaultCursor[ dc_arrow ];
+
+#elif defined( WIN32 )
+
+ s_pDefaultCursor[ dc_none ] = NULL;
+ s_pDefaultCursor[ dc_arrow ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_NORMAL);
+ s_pDefaultCursor[ dc_ibeam ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_IBEAM);
+ s_pDefaultCursor[ dc_hourglass ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_WAIT);
+ s_pDefaultCursor[ dc_crosshair ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_CROSS);
+ s_pDefaultCursor[ dc_waitarrow ] =(HICON)LoadCursor(NULL, (LPCTSTR)32650);
+ s_pDefaultCursor[ dc_up ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_UP);
+ s_pDefaultCursor[ dc_sizenwse ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_SIZENWSE);
+ s_pDefaultCursor[ dc_sizenesw ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_SIZENESW);
+ s_pDefaultCursor[ dc_sizewe ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_SIZEWE);
+ s_pDefaultCursor[ dc_sizens ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_SIZENS);
+ s_pDefaultCursor[ dc_sizeall ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_SIZEALL);
+ s_pDefaultCursor[ dc_no ] =(HICON)LoadCursor(NULL, (LPCTSTR)OCR_NO);
+ s_pDefaultCursor[ dc_hand ] =(HICON)LoadCursor(NULL, (LPCTSTR)32649);
+
+ s_hCurrentCursor = s_pDefaultCursor[ dc_arrow ];
+
+#endif
+
+ s_bCursorLocked = false;
+ s_bCursorVisible = true;
+ s_nForceCursorVisibleCount = 0;
+}
+
+
+#define USER_CURSOR_MASK 0x80000000
+
+#ifdef WIN32
+//-----------------------------------------------------------------------------
+// Purpose: Simple manager for user loaded windows cursors in vgui
+//-----------------------------------------------------------------------------
+class CUserCursorManager
+{
+public:
+ void Shutdown();
+ vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID );
+ bool LookupCursor( vgui::HCursor cursor, HCURSOR& handle );
+private:
+ CUtlDict< HCURSOR, int > m_UserCursors;
+};
+
+void CUserCursorManager::Shutdown()
+{
+ for ( int i = m_UserCursors.First() ; i != m_UserCursors.InvalidIndex(); i = m_UserCursors.Next( i ) )
+ {
+ ::DestroyCursor( m_UserCursors[ i ] );
+ }
+ m_UserCursors.RemoveAll();
+}
+
+vgui::HCursor CUserCursorManager::CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
+{
+ char fn[ 512 ];
+ Q_strncpy( fn, curOrAniFile, sizeof( fn ) );
+ Q_strlower( fn );
+ Q_FixSlashes( fn );
+
+ int cursorIndex = m_UserCursors.Find( fn );
+ if ( cursorIndex != m_UserCursors.InvalidIndex() )
+ {
+ return cursorIndex | USER_CURSOR_MASK;
+ }
+
+ g_pFullFileSystem->GetLocalCopy( fn );
+
+ char fullpath[ 512 ];
+ g_pFullFileSystem->RelativePathToFullPath( fn, pPathID, fullpath, sizeof( fullpath ) );
+
+ HCURSOR newCursor = (HCURSOR)LoadCursorFromFile( fullpath );
+ cursorIndex = m_UserCursors.Insert( fn, newCursor );
+ return cursorIndex | USER_CURSOR_MASK;
+}
+
+bool CUserCursorManager::LookupCursor( vgui::HCursor cursor, HCURSOR& handle )
+{
+ if ( !( (int)cursor & USER_CURSOR_MASK ) )
+ {
+ handle = 0;
+ return false;
+ }
+
+ int cursorIndex = (int)cursor & ~USER_CURSOR_MASK;
+ if ( !m_UserCursors.IsValidIndex( cursorIndex ) )
+ {
+ handle = 0;
+ return false;
+ }
+
+ handle = m_UserCursors[ cursorIndex ];
+ return true;
+}
+
+static CUserCursorManager g_UserCursors;
+#endif
+
+vgui::HCursor Cursor_CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
+{
+#ifdef WIN32
+ return g_UserCursors.CreateCursorFromFile( curOrAniFile, pPathID );
+#else
+ return dc_user;
+#endif
+}
+
+
+void Cursor_ClearUserCursors()
+{
+#ifdef WIN32
+ g_UserCursors.Shutdown();
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Initializes all the textures for software cursors
+//-----------------------------------------------------------------------------
+int InitSoftwareCursorTexture( const char *pchFilename )
+{
+ if( !pchFilename || !*pchFilename )
+ return -1;
+
+ int nTextureID = g_MatSystemSurface.DrawGetTextureId( pchFilename );
+ if( nTextureID == -1 )
+ {
+ nTextureID = g_MatSystemSurface.CreateNewTextureID();
+ g_MatSystemSurface.DrawSetTextureFile( nTextureID, pchFilename, true, false );
+ }
+ return nTextureID;
+}
+
+void InitSoftwareCursors()
+{
+ if( s_bSoftwareCursorsInitialized )
+ return;
+
+ memset( s_rfSoftwareCursorOffset, 0, sizeof( s_rfSoftwareCursorOffset ) );
+
+ s_rnSoftwareCursorID[dc_none] = -1;
+ s_rnSoftwareCursorID[dc_arrow] =InitSoftwareCursorTexture( "vgui/cursors/arrow" );
+ s_rnSoftwareCursorID[dc_ibeam] =InitSoftwareCursorTexture( "vgui/cursors/ibeam" );
+ s_rnSoftwareCursorID[dc_hourglass]=InitSoftwareCursorTexture( "vgui/cursors/hourglass" );
+ s_rnSoftwareCursorID[dc_crosshair]=InitSoftwareCursorTexture( "vgui/cursors/crosshair" );
+ s_rnSoftwareCursorID[dc_waitarrow]=InitSoftwareCursorTexture( "vgui/cursors/waitarrow" );
+ s_rnSoftwareCursorID[dc_up] =InitSoftwareCursorTexture( "vgui/cursors/up" );
+ s_rnSoftwareCursorID[dc_sizenwse] =InitSoftwareCursorTexture( "vgui/cursors/sizenwse" );
+ s_rnSoftwareCursorID[dc_sizenesw] =InitSoftwareCursorTexture( "vgui/cursors/sizenesw" );
+ s_rnSoftwareCursorID[dc_sizewe] =InitSoftwareCursorTexture( "vgui/cursors/sizewe" );
+ s_rnSoftwareCursorID[dc_sizens] =InitSoftwareCursorTexture( "vgui/cursors/sizens" );
+ s_rnSoftwareCursorID[dc_sizeall] =InitSoftwareCursorTexture( "vgui/cursors/sizeall" );
+ s_rnSoftwareCursorID[dc_no] =InitSoftwareCursorTexture( "vgui/cursors/no" );
+ s_rnSoftwareCursorID[dc_hand] =InitSoftwareCursorTexture( "vgui/cursors/hand" );
+
+ // handle the cursor hotspots not being at their origin
+ s_rfSoftwareCursorOffset[dc_arrow][0] = -0.1;
+ s_rfSoftwareCursorOffset[dc_arrow][1] = -0.1;
+ s_rfSoftwareCursorOffset[dc_ibeam][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_ibeam][1] = -0.8;
+ s_rfSoftwareCursorOffset[dc_hourglass][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_hourglass][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_crosshair][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_crosshair][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_waitarrow][0] = -0.1;
+ s_rfSoftwareCursorOffset[dc_waitarrow][1] = -0.1;
+ s_rfSoftwareCursorOffset[dc_up][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_up][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizenwse][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizenwse][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizenesw][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizenesw][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizewe][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizewe][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizens][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizens][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizeall][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_sizeall][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_no][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_no][1] = -0.5;
+ s_rfSoftwareCursorOffset[dc_hand][0] = -0.5;
+ s_rfSoftwareCursorOffset[dc_hand][1] = -0.5;
+
+ s_bSoftwareCursorsInitialized = true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Selects a cursor
+//-----------------------------------------------------------------------------
+void CursorSelect(HCursor hCursor)
+{
+ if ( ( hCursor == dc_alwaysvisible_push ) || ( hCursor == dc_alwaysvisible_pop ) )
+ {
+ // CConPanel in engine/console.cpp does a SetCursor(null). So when the TF2 chat window pops up
+ // and there are console commands showing and fading out in the top left, our chat window
+ // will have a cursor show/hide fight with them. So the cursor flickers or doesn't show up
+ // at all. Unfortunately on Linux, it's even worse since we recenter the mouse when it's
+ // not shown - so we added this API call which causes cursor.cpp to always show the cursor.
+ s_nForceCursorVisibleCount += ( hCursor == dc_alwaysvisible_push ? 1 : -1 );
+ Assert( s_nForceCursorVisibleCount >= 0 );
+
+ if( ( s_nForceCursorVisibleCount && !s_bCursorVisible ) ||
+ ( !s_nForceCursorVisibleCount && s_bCursorVisible ) )
+ {
+ ActivateCurrentCursor();
+ }
+ return;
+ }
+
+ if (s_bCursorLocked)
+ return;
+
+#if defined( WIN32 ) && !defined( USE_SDL )
+ s_bCursorVisible = true;
+ switch (hCursor)
+ {
+ case dc_user:
+ case dc_none:
+ case dc_blank:
+ s_bCursorVisible = false;
+ break;
+
+ case dc_arrow:
+ case dc_waitarrow:
+ case dc_ibeam:
+ case dc_hourglass:
+ case dc_crosshair:
+ case dc_up:
+ case dc_sizenwse:
+ case dc_sizenesw:
+ case dc_sizewe:
+ case dc_sizens:
+ case dc_sizeall:
+ case dc_no:
+ case dc_hand:
+ if( !s_bSoftwareCursorActive )
+ {
+ s_hCurrentCursor = s_pDefaultCursor[hCursor];
+ }
+ else
+ {
+ s_nSoftwareCursorTexture = s_rnSoftwareCursorID[ hCursor ];
+ s_fSoftwareCursorOffsetX = s_rfSoftwareCursorOffset[ hCursor ][0];
+ s_fSoftwareCursorOffsetY = s_rfSoftwareCursorOffset[ hCursor ][1];
+ }
+ break;
+
+ default:
+ {
+ HCURSOR custom = 0;
+ if ( g_UserCursors.LookupCursor( hCursor, custom ) && custom != 0 )
+ {
+ s_hCurrentCursor = custom;
+ }
+ else
+ {
+ s_bCursorVisible = false;
+ Assert(0);
+ }
+ }
+ break;
+ }
+
+ ActivateCurrentCursor();
+
+#elif defined( USE_SDL )
+
+ switch (hCursor)
+ {
+ case dc_user:
+ case dc_none:
+ case dc_blank:
+ s_bCursorVisible = false;
+ break;
+
+ default:
+ // We don't support custom cursors at the moment (but could, if necessary).
+ // Fall through and use the arrow for now...
+ Assert(0);
+ hCursor = dc_arrow;
+
+ case dc_arrow:
+ case dc_waitarrow:
+ case dc_ibeam:
+ case dc_hourglass:
+ case dc_crosshair:
+ case dc_up:
+ case dc_sizenwse:
+ case dc_sizenesw:
+ case dc_sizewe:
+ case dc_sizens:
+ case dc_sizeall:
+ case dc_no:
+ case dc_hand:
+ s_bCursorVisible = true;
+ if( !s_bSoftwareCursorActive )
+ {
+ s_hCurrentCursor = s_pDefaultCursor[hCursor];
+ }
+ else
+ {
+ s_nSoftwareCursorTexture = s_rnSoftwareCursorID[ hCursor ];
+ s_fSoftwareCursorOffsetX = s_rfSoftwareCursorOffset[ hCursor ][0];
+ s_fSoftwareCursorOffsetY = s_rfSoftwareCursorOffset[ hCursor ][1];
+ }
+ break;
+ }
+
+ ActivateCurrentCursor();
+
+#else
+#error
+#endif
+
+}
+
+
+//-----------------------------------------------------------------------------
+// Hides the hardware cursor
+//-----------------------------------------------------------------------------
+void HideHardwareCursor()
+{
+#if defined( WIN32 ) && !defined( USE_SDL )
+ ::SetCursor(NULL);
+#elif defined( USE_SDL )
+ //if ( s_hCurrentlySetCursor != s_pDefaultCursor[ dc_none ] )
+ {
+ s_hCurrentlySetCursor = s_pDefaultCursor[ dc_none ];
+ g_pLauncherMgr->SetMouseCursor( s_hCurrentlySetCursor );
+ g_pLauncherMgr->SetMouseVisible( false );
+ }
+#else
+#error
+#endif
+}
+
+
+//-----------------------------------------------------------------------------
+// Activates the current cursor
+//-----------------------------------------------------------------------------
+void ActivateCurrentCursor()
+{
+ if( s_bSoftwareCursorActive )
+ {
+ HideHardwareCursor();
+ return;
+ }
+
+ if ( s_bCursorVisible || ( s_nForceCursorVisibleCount > 0 ) )
+ {
+#if defined( WIN32 ) && !defined( USE_SDL )
+ ::SetCursor(s_hCurrentCursor);
+#elif defined( USE_SDL )
+ if (s_hCurrentlySetCursor != s_hCurrentCursor )
+ {
+ s_hCurrentlySetCursor = s_hCurrentCursor;
+ g_pLauncherMgr->SetMouseCursor( s_hCurrentlySetCursor );
+ g_pLauncherMgr->SetMouseVisible( true );
+ }
+#else
+#error
+#endif
+ }
+ else
+ {
+ HideHardwareCursor();
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: prevents vgui from changing the cursor
+//-----------------------------------------------------------------------------
+void LockCursor( bool bEnable )
+{
+ s_bCursorLocked = bEnable;
+ ActivateCurrentCursor();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: unlocks the cursor state
+//-----------------------------------------------------------------------------
+bool IsCursorLocked()
+{
+ return s_bCursorLocked;
+}
+
+
+//-----------------------------------------------------------------------------
+// handles mouse movement
+//-----------------------------------------------------------------------------
+void CursorSetPos( void *hwnd, int x, int y )
+{
+#if defined( USE_SDL )
+ if ( s_bCursorVisible )
+#endif
+ g_pInputSystem->SetCursorPosition( x, y );
+}
+
+void CursorGetPos(void *hwnd, int &x, int &y)
+{
+#if defined ( USE_SDL ) && !defined( PLATFORM_WINDOWS )
+ if ( s_bCursorVisible )
+ {
+ SDL_GetMouseState( &x, &y );
+
+ int windowHeight = 0;
+ int windowWidth = 0;
+ //unsigned int ignored;
+ SDL_GetWindowSize( ( SDL_Window * )g_pLauncherMgr->GetWindowRef(), &windowWidth, &windowHeight );
+
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ int rx, ry, width, height;
+ pRenderContext->GetViewport( rx, ry, width, height );
+
+ if ( !s_bSoftwareCursorActive && (width != windowWidth || height != windowHeight ) )
+ {
+ // scale the x/y back into the co-ords of the back buffer, not the scaled up window
+ //DevMsg( "Mouse x:%d y:%d %d %d %d %d\n", x, y, width, windowWidth, height, abs( height - windowHeight ) );
+ x = x * (float)width/windowWidth;
+ y = y * (float)height/windowHeight;
+ }
+ }
+ else
+ {
+ // cursor is invisible, just say we have it pinned to the middle of the screen
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ int rx, ry, width, height;
+ pRenderContext->GetViewport( rx, ry, width, height );
+ x = rx + width/2;
+ y = ry + height/2;
+ //printf( "Mouse(inv) x:%d y:%d %d %d\n", x, y, width, height );
+ }
+#else
+ POINT pt;
+
+ // Default implementation
+ VCRHook_GetCursorPos( &pt );
+ VCRHook_ScreenToClient((HWND)hwnd, &pt);
+ x = pt.x; y = pt.y;
+#endif
+}
+
+
+void EnableSoftwareCursor( bool bEnable )
+{
+ if( bEnable )
+ InitSoftwareCursors();
+
+ bool bWasEnabled = s_bSoftwareCursorActive;
+ s_bSoftwareCursorActive = bEnable;
+
+ // set the cursor to the arrow (or none if appropriate) if we're activating the
+ // software cursor. VGUI will likely update it again soon, but this will give
+ // us some kind of cursor in the meantime
+ if( !bWasEnabled && bEnable )
+ {
+ if( s_bCursorVisible )
+ CursorSelect( dc_arrow );
+ }
+}
+
+bool ShouldDrawSoftwareCursor()
+{
+ return s_bSoftwareCursorActive && s_bCursorVisible;
+}
+
+int GetSoftwareCursorTexture( float *px, float *py )
+{
+ if( px && py )
+ {
+ *px = s_fSoftwareCursorOffsetX;
+ *py = s_fSoftwareCursorOffsetY;
+ }
+ return s_nSoftwareCursorTexture;
+}
+
+
diff --git a/vguimatsurface/Cursor.h b/vguimatsurface/Cursor.h
new file mode 100644
index 0000000..10166df
--- /dev/null
+++ b/vguimatsurface/Cursor.h
@@ -0,0 +1,75 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Methods associated with the cursor
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef MATSURFACE_CURSOR_H
+#define MATSURFACE_CURSOR_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "VGuiMatSurface/IMatSystemSurface.h"
+#include <vgui/Cursor.h>
+
+//-----------------------------------------------------------------------------
+// Initializes cursors
+//-----------------------------------------------------------------------------
+void InitCursors();
+
+
+//-----------------------------------------------------------------------------
+// Selects a cursor
+//-----------------------------------------------------------------------------
+void CursorSelect(vgui::HCursor hCursor);
+
+
+//-----------------------------------------------------------------------------
+// Activates the current cursor
+//-----------------------------------------------------------------------------
+void ActivateCurrentCursor();
+
+
+//-----------------------------------------------------------------------------
+// Handles software cursors
+//-----------------------------------------------------------------------------
+void EnableSoftwareCursor( bool bEnable );
+bool ShouldDrawSoftwareCursor();
+int GetSoftwareCursorTexture( float *px, float *py );
+
+//-----------------------------------------------------------------------------
+// handles mouse movement
+//-----------------------------------------------------------------------------
+void CursorSetPos(void *hwnd, int x, int y);
+void CursorGetPos(void *hwnd, int &x, int &y);
+
+
+//-----------------------------------------------------------------------------
+// Purpose: prevents vgui from changing the cursor
+//-----------------------------------------------------------------------------
+void LockCursor( bool bEnable );
+
+
+//-----------------------------------------------------------------------------
+// Purpose: unlocks the cursor state
+//-----------------------------------------------------------------------------
+bool IsCursorLocked();
+
+//-----------------------------------------------------------------------------
+// Purpose: loads a custom cursor file from the file system
+//-----------------------------------------------------------------------------
+vgui::HCursor Cursor_CreateCursorFromFile( char const *curOrAniFile, char const *pPathID );
+
+// Helper for shutting down cursors
+void Cursor_ClearUserCursors();
+
+#endif // MATSURFACE_CURSOR_H
+
+
+
+
+
diff --git a/vguimatsurface/FontTextureCache.cpp b/vguimatsurface/FontTextureCache.cpp
new file mode 100644
index 0000000..d94e9af
--- /dev/null
+++ b/vguimatsurface/FontTextureCache.cpp
@@ -0,0 +1,512 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#if defined ( WIN32 ) && !defined( _X360 )
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#elif defined( OSX )
+#include <Carbon/Carbon.h>
+#elif defined( LINUX )
+//#error
+#elif defined( _X360 )
+#else
+#error
+#endif
+#include "FontTextureCache.h"
+#include "MatSystemSurface.h"
+#include <vgui_surfacelib/BitmapFont.h>
+#include <vgui/IVGui.h>
+#include <vgui_controls/Controls.h>
+#include "bitmap/imageformat.h"
+#include "vtf/vtf.h"
+#include "materialsystem/imaterialvar.h"
+#include "materialsystem/itexture.h"
+#include "tier1/KeyValues.h"
+#include "tier1/utlbuffer.h"
+#include "pixelwriter.h"
+#include "tier0/icommandline.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern CMatSystemSurface g_MatSystemSurface;
+static int g_FontRenderBoundingBoxes = -1;
+
+#define TEXTURE_PAGE_WIDTH 256
+#define TEXTURE_PAGE_HEIGHT 256
+
+// row size
+int CFontTextureCache::s_pFontPageSize[FONT_PAGE_SIZE_COUNT] =
+{
+ 16,
+ 32,
+ 64,
+ 128,
+ 256,
+};
+
+static bool g_mat_texture_outline_fonts = false;
+CON_COMMAND( mat_texture_outline_fonts, "Outline fonts textures." )
+{
+ g_mat_texture_outline_fonts = !g_mat_texture_outline_fonts;
+ Msg( "mat_texture_outline_fonts: %d\n", g_mat_texture_outline_fonts );
+ g_MatSystemSurface.ResetFontCaches();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+//-----------------------------------------------------------------------------
+CFontTextureCache::CFontTextureCache()
+ : m_CharCache(0, 256, CacheEntryLessFunc)
+{
+ Clear();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+CFontTextureCache::~CFontTextureCache()
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Resets the cache
+//-----------------------------------------------------------------------------
+void CFontTextureCache::Clear()
+{
+ // remove all existing data
+ m_CharCache.RemoveAll();
+ m_PageList.RemoveAll();
+
+ // reinitialize
+ CacheEntry_t listHead = { 0, 0 };
+ m_LRUListHeadIndex = m_CharCache.Insert(listHead);
+
+ m_CharCache[m_LRUListHeadIndex].nextEntry = m_LRUListHeadIndex;
+ m_CharCache[m_LRUListHeadIndex].prevEntry = m_LRUListHeadIndex;
+
+ for (int i = 0; i < FONT_PAGE_SIZE_COUNT; ++i)
+ {
+ m_pCurrPage[i] = -1;
+ }
+ m_FontPages.SetLessFunc( DefLessFunc( vgui::HFont ) );
+ m_FontPages.RemoveAll();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: comparison function for cache entries
+//-----------------------------------------------------------------------------
+bool CFontTextureCache::CacheEntryLessFunc(CacheEntry_t const &lhs, CacheEntry_t const &rhs)
+{
+ if (lhs.font < rhs.font)
+ return true;
+ else if (lhs.font > rhs.font)
+ return false;
+
+ return (lhs.wch < rhs.wch);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the texture info for the given char & font
+//-----------------------------------------------------------------------------
+bool CFontTextureCache::GetTextureForChar( vgui::HFont font, vgui::FontDrawType_t type, wchar_t wch, int *textureID, float **texCoords )
+{
+ // Ask for just one character
+ return GetTextureForChars( font, type, &wch, textureID, texCoords, 1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the texture info for the given chars & font
+//-----------------------------------------------------------------------------
+bool CFontTextureCache::GetTextureForChars( vgui::HFont font, vgui::FontDrawType_t type, const wchar_t *wch, int *textureID, float **texCoords, int numChars )
+{
+ Assert( wch && textureID && texCoords );
+ Assert( numChars >= 1 );
+
+ if ( type == vgui::FONT_DRAW_DEFAULT )
+ {
+ type = g_MatSystemSurface.IsFontAdditive( font ) ? vgui::FONT_DRAW_ADDITIVE : vgui::FONT_DRAW_NONADDITIVE;
+ }
+
+ int typePage = (int)type - 1;
+ typePage = clamp( typePage, 0, (int)vgui::FONT_DRAW_TYPE_COUNT - 1 );
+
+ if ( FontManager().IsBitmapFont( font ) )
+ {
+ const int MAX_BITMAP_CHARS = 256;
+ if ( numChars > MAX_BITMAP_CHARS )
+ {
+ // Increase MAX_BITMAP_CHARS
+ Assert( 0 );
+ return false;
+ }
+
+ for ( int i = 0; i < numChars; i++ )
+ {
+ static float sTexCoords[ 4*MAX_BITMAP_CHARS ];
+ CBitmapFont *pWinFont;
+ float left, top, right, bottom;
+ int index;
+ Page_t *pPage;
+
+ pWinFont = reinterpret_cast< CBitmapFont* >( FontManager().GetFontForChar( font, wch[i] ) );
+ if ( !pWinFont )
+ {
+ // bad font handle
+ return false;
+ }
+
+ // get the texture coords
+ pWinFont->GetCharCoords( wch[i], &left, &top, &right, &bottom );
+ sTexCoords[i*4 + 0] = left;
+ sTexCoords[i*4 + 1] = top;
+ sTexCoords[i*4 + 2] = right;
+ sTexCoords[i*4 + 3] = bottom;
+
+ // find font handle in our list of ready pages
+ index = m_FontPages.Find( font );
+ if ( index == m_FontPages.InvalidIndex() )
+ {
+ // not found, create the texture id and its materials
+ index = m_FontPages.Insert( font );
+ pPage = &m_FontPages.Element( index );
+
+ for (int type = 0; type < FONT_DRAW_TYPE_COUNT; ++type )
+ {
+ pPage->textureID[type] = g_MatSystemSurface.CreateNewTextureID( false );
+ }
+ CreateFontMaterials( *pPage, pWinFont->GetTexturePage(), true );
+ }
+
+ texCoords[i] = &(sTexCoords[ i*4 ]);
+ textureID[i] = m_FontPages.Element( index ).textureID[typePage];
+ }
+ }
+ else
+ {
+ struct newPageEntry_t
+ {
+ int page; // The font page a new character will go in
+ int drawX; // X location within the font page
+ int drawY; // Y location within the font page
+ };
+
+ // Determine how many characters need to have their texture generated
+ int numNewChars = 0;
+ int maxNewCharTexels = 0;
+ int totalNewCharTexels = 0;
+ newChar_t *newChars = (newChar_t *)_alloca( numChars*sizeof( newChar_t ) );
+ newPageEntry_t *newEntries = (newPageEntry_t *)_alloca( numChars*sizeof( newPageEntry_t ) );
+
+ font_t *winFont = FontManager().GetFontForChar( font, wch[0] );
+ if ( !winFont )
+ return false;
+
+ for ( int i = 0; i < numChars; i++ )
+ {
+ CacheEntry_t cacheItem;
+ cacheItem.font = font;
+ cacheItem.wch = wch[i];
+ HCacheEntry cacheHandle = m_CharCache.Find( cacheItem );
+ if ( ! m_CharCache.IsValidIndex( cacheHandle ) )
+ {
+ // All characters must come out of the same font
+ if ( winFont != FontManager().GetFontForChar( font, wch[i] ) )
+ return false;
+
+ // get the char details
+ int a, b, c;
+ winFont->GetCharABCWidths( wch[i], a, b, c );
+ int fontWide = max( b, 1 );
+ int fontTall = max( winFont->GetHeight(), 1 );
+ if ( winFont->GetUnderlined() )
+ {
+ fontWide += ( a + c );
+ }
+
+ // Get a texture to render into
+ int page, drawX, drawY, twide, ttall;
+ if ( !AllocatePageForChar( fontWide, fontTall, page, drawX, drawY, twide, ttall ) )
+ return false;
+
+ // accumulate data to pass to GetCharsRGBA below
+ newEntries[ numNewChars ].page = page;
+ newEntries[ numNewChars ].drawX = drawX;
+ newEntries[ numNewChars ].drawY = drawY;
+ newChars[ numNewChars ].wch = wch[i];
+ newChars[ numNewChars ].fontWide = fontWide;
+ newChars[ numNewChars ].fontTall = fontTall;
+ newChars[ numNewChars ].offset = 4*totalNewCharTexels;
+ totalNewCharTexels += fontWide*fontTall;
+ maxNewCharTexels = max( maxNewCharTexels, fontWide*fontTall );
+ numNewChars++;
+
+ // set the cache info
+ cacheItem.page = page;
+
+ // the 0.5 texel offset is done in CMatSystemTexture::SetMaterial() / CMatSystemSurface::StartDrawing()
+ double adjust = 0.0f;
+
+ cacheItem.texCoords[0] = (float)( (double)drawX / ((double)twide + adjust) );
+ cacheItem.texCoords[1] = (float)( (double)drawY / ((double)ttall + adjust) );
+ cacheItem.texCoords[2] = (float)( (double)(drawX + fontWide) / (double)twide );
+ cacheItem.texCoords[3] = (float)( (double)(drawY + fontTall) / (double)ttall );
+
+ m_CharCache.Insert(cacheItem);
+ cacheHandle = m_CharCache.Find( cacheItem );
+ Assert( m_CharCache.IsValidIndex( cacheHandle ) );
+ }
+
+ int page = m_CharCache[cacheHandle].page;
+ textureID[i] = m_PageList[page].textureID[typePage];
+ texCoords[i] = m_CharCache[cacheHandle].texCoords;
+ }
+
+ // Generate texture data for all newly-encountered characters
+ if ( numNewChars > 0 )
+ {
+
+#ifdef _X360
+ if ( numNewChars > 1 )
+ {
+ MEM_ALLOC_CREDIT();
+
+ // Use the 360 fast path that generates multiple characters at once
+ int newCharDataSize = totalNewCharTexels*4;
+ CUtlBuffer newCharData( newCharDataSize, newCharDataSize, 0 );
+ unsigned char *pRGBA = (unsigned char *)newCharData.Base();
+ winFont->GetCharsRGBA( newChars, numNewChars, pRGBA );
+
+ // Copy the data into our font pages
+ for ( int i = 0; i < numNewChars; i++ )
+ {
+ newChar_t & newChar = newChars[i];
+ newPageEntry_t & newEntry = newEntries[i];
+
+ // upload the new sub texture
+ // NOTE: both textureIDs reference the same ITexture, so we're ok
+ g_MatSystemSurface.DrawSetTexture( m_PageList[newEntry.page].textureID[typePage] );
+ unsigned char *characterRGBA = pRGBA + newChar.offset;
+ g_MatSystemSurface.DrawSetSubTextureRGBA( m_PageList[newEntry.page].textureID[typePage], newEntry.drawX, newEntry.drawY, characterRGBA, newChar.fontWide, newChar.fontTall );
+ }
+ }
+ else
+#endif
+ {
+ // create a buffer for new characters to be rendered into
+ int nByteCount = maxNewCharTexels * 4;
+ unsigned char *pRGBA = (unsigned char *)_alloca( nByteCount );
+
+ // Generate characters individually
+ for ( int i = 0; i < numNewChars; i++ )
+ {
+ newChar_t & newChar = newChars[i];
+ newPageEntry_t & newEntry = newEntries[i];
+
+ // render the character into the buffer
+ Q_memset( pRGBA, 0, nByteCount );
+
+ winFont->GetCharRGBA( newChar.wch, newChar.fontWide, newChar.fontTall, pRGBA );
+
+ if ( g_mat_texture_outline_fonts )
+ {
+ int width = newChar.fontWide;
+ int height = newChar.fontTall;
+
+ CPixelWriter pixelWriter;
+ pixelWriter.SetPixelMemory( IMAGE_FORMAT_RGBA8888, pRGBA, width * sizeof( BGRA8888_t ) );
+ for( int x = 0; x < width; x++ )
+ {
+ pixelWriter.Seek( x, 0 );
+ pixelWriter.WritePixel( 255, 0, 255, 255 );
+ pixelWriter.Seek( x, height - 1 );
+ pixelWriter.WritePixel( 255, 0, 255, 255 );
+ }
+ for( int y = 0; y < height; y++ )
+ {
+ if ( y < 4 || y > height - 4 )
+ {
+ pixelWriter.Seek( 0, y );
+ pixelWriter.WritePixel( 255, 0, 255, 255 );
+ pixelWriter.Seek( width - 1, y );
+ pixelWriter.WritePixel( 255, 0, 255, 255 );
+ }
+ }
+ }
+
+ // upload the new sub texture
+ // NOTE: both textureIDs reference the same ITexture, so we're ok)
+ g_MatSystemSurface.DrawSetTexture( m_PageList[newEntry.page].textureID[typePage] );
+ g_MatSystemSurface.DrawSetSubTextureRGBA( m_PageList[newEntry.page].textureID[typePage], newEntry.drawX, newEntry.drawY, pRGBA, newChar.fontWide, newChar.fontTall );
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+
+//-----------------------------------------------------------------------------
+// Creates font materials
+//-----------------------------------------------------------------------------
+void CFontTextureCache::CreateFontMaterials( Page_t &page, ITexture *pFontTexture, bool bitmapFont )
+{
+ // The normal material
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetInt( "$vertexcolor", 1 );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$ignorez", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+ pVMTKeyValues->SetInt( "$translucent", 1 );
+ pVMTKeyValues->SetString( "$basetexture", pFontTexture->GetName() );
+ IMaterial *pMaterial = g_pMaterialSystem->CreateMaterial( "__fontpage", pVMTKeyValues );
+ pMaterial->Refresh();
+
+ int typePageNonAdditive = (int)vgui::FONT_DRAW_NONADDITIVE-1;
+ g_MatSystemSurface.DrawSetTextureMaterial( page.textureID[typePageNonAdditive], pMaterial );
+ pMaterial->DecrementReferenceCount();
+
+ // The additive material
+ pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetInt( "$vertexcolor", 1 );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$ignorez", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+ pVMTKeyValues->SetInt( "$translucent", 1 );
+ pVMTKeyValues->SetInt( "$additive", 1 );
+ pVMTKeyValues->SetString( "$basetexture", pFontTexture->GetName() );
+ pMaterial = g_pMaterialSystem->CreateMaterial( "__fontpage_additive", pVMTKeyValues );
+ pMaterial->Refresh();
+
+ int typePageAdditive = (int)vgui::FONT_DRAW_ADDITIVE-1;
+ if ( bitmapFont )
+ {
+ g_MatSystemSurface.DrawSetTextureMaterial( page.textureID[typePageAdditive], pMaterial );
+ }
+ else
+ {
+ g_MatSystemSurface.ReferenceProceduralMaterial( page.textureID[typePageAdditive], page.textureID[typePageNonAdditive], pMaterial );
+ }
+ pMaterial->DecrementReferenceCount();
+}
+
+//-----------------------------------------------------------------------------
+// Computes the page size given a character height
+//-----------------------------------------------------------------------------
+int CFontTextureCache::ComputePageType( int charTall ) const
+{
+ for (int i = 0; i < FONT_PAGE_SIZE_COUNT; ++i)
+ {
+ if ( charTall < s_pFontPageSize[i] )
+ return i;
+ }
+
+ return -1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: allocates a new page for a given character
+//-----------------------------------------------------------------------------
+bool CFontTextureCache::AllocatePageForChar(int charWide, int charTall, int &pageIndex, int &drawX, int &drawY, int &twide, int &ttall)
+{
+ // see if there is room in the last page for this character
+ int nPageType = ComputePageType( charTall );
+ if ( nPageType < 0 )
+ {
+ Assert( !"Font is too tall for texture cache of glyphs\n" );
+ return false;
+ }
+
+ pageIndex = m_pCurrPage[nPageType];
+
+ int nNextX = 0;
+ bool bNeedsNewPage = true;
+ if ( pageIndex > -1 )
+ {
+ Page_t &page = m_PageList[ pageIndex ];
+
+ nNextX = page.nextX + charWide;
+
+ // make sure we have room on the current line of the texture page
+ if ( nNextX > page.wide )
+ {
+ // move down a line
+ page.nextX = 0;
+ nNextX = charWide;
+ page.nextY += page.tallestCharOnLine;
+ page.tallestCharOnLine = charTall;
+ }
+ page.tallestCharOnLine = max( page.tallestCharOnLine, (short)charTall );
+
+ bNeedsNewPage = ((page.nextY + page.tallestCharOnLine) > page.tall);
+ }
+
+ if ( bNeedsNewPage )
+ {
+ // allocate a new page
+ pageIndex = m_PageList.AddToTail();
+ Page_t &newPage = m_PageList[pageIndex];
+ m_pCurrPage[nPageType] = pageIndex;
+
+ for (int i = 0; i < FONT_DRAW_TYPE_COUNT; ++i )
+ {
+ newPage.textureID[i] = g_MatSystemSurface.CreateNewTextureID( true );
+ }
+
+ newPage.maxFontHeight = s_pFontPageSize[nPageType];
+ newPage.wide = TEXTURE_PAGE_WIDTH;
+ newPage.tall = TEXTURE_PAGE_HEIGHT;
+ newPage.nextX = 0;
+ newPage.nextY = 0;
+ newPage.tallestCharOnLine = charTall;
+
+ nNextX = charWide;
+
+ static int nFontPageId = 0;
+ char pTextureName[64];
+ Q_snprintf( pTextureName, 64, "__font_page_%d", nFontPageId );
+ ++nFontPageId;
+
+ MEM_ALLOC_CREDIT();
+ ITexture *pTexture = g_pMaterialSystem->CreateProceduralTexture(
+ pTextureName,
+ TEXTURE_GROUP_VGUI,
+ newPage.wide,
+ newPage.tall,
+ IMAGE_FORMAT_RGBA8888,
+ TEXTUREFLAGS_POINTSAMPLE | TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT |
+ TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD | TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY );
+
+ CreateFontMaterials( newPage, pTexture );
+
+ pTexture->DecrementReferenceCount();
+
+ if ( IsPC() || !IsDebug() )
+ {
+ // clear the texture from the inital checkerboard to black
+ // allocate for 32bpp format
+ int nByteCount = TEXTURE_PAGE_WIDTH * TEXTURE_PAGE_HEIGHT * 4;
+ unsigned char *pRGBA = (unsigned char *)_alloca( nByteCount );
+ Q_memset( pRGBA, 0, nByteCount );
+
+ int typePageNonAdditive = (int)(vgui::FONT_DRAW_NONADDITIVE)-1;
+ g_MatSystemSurface.DrawSetTextureRGBA( newPage.textureID[typePageNonAdditive], pRGBA, newPage.wide, newPage.tall, false, false );
+ }
+ }
+
+ // output the position
+ Page_t &page = m_PageList[ pageIndex ];
+ drawX = page.nextX;
+ drawY = page.nextY;
+ twide = page.wide;
+ ttall = page.tall;
+
+ // Update the next position to draw in
+ page.nextX = nNextX + 1;
+ return true;
+}
diff --git a/vguimatsurface/FontTextureCache.h b/vguimatsurface/FontTextureCache.h
new file mode 100644
index 0000000..1f12e3c
--- /dev/null
+++ b/vguimatsurface/FontTextureCache.h
@@ -0,0 +1,102 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef FONTTEXTURECACHE_H
+#define FONTTEXTURECACHE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include "vgui_surfacelib/FontManager.h"
+#include "utlrbtree.h"
+#include <vgui/ISurface.h>
+#include "utlmap.h"
+
+class ITexture;
+
+//-----------------------------------------------------------------------------
+// Purpose: manages texture memory for unicode fonts in vgui
+//-----------------------------------------------------------------------------
+class CFontTextureCache
+{
+public:
+ CFontTextureCache();
+ ~CFontTextureCache();
+
+ // returns a texture ID and a pointer to an array of 4 texture coords for the given character & font
+ // generates+uploads more texture if necessary
+ bool GetTextureForChar( vgui::HFont font, vgui::FontDrawType_t type, wchar_t wch, int *textureID, float **texCoords );
+
+ // for each character in an array (not assumed to be a NULL-terminated string), returns a
+ // texture ID and a pointer to an array of 4 texture coords for the given character & font
+ // generates+uploads more texture if necessary
+ bool GetTextureForChars( vgui::HFont font, vgui::FontDrawType_t type, const wchar_t *wch, int *textureID, float **texCoords, int numChars = 1 );
+
+ // clears the cache
+ void Clear();
+
+private:
+ // NOTE: If you change this, change s_pFontPageSize
+ enum
+ {
+ FONT_PAGE_SIZE_16,
+ FONT_PAGE_SIZE_32,
+ FONT_PAGE_SIZE_64,
+ FONT_PAGE_SIZE_128,
+ FONT_PAGE_SIZE_256,
+ FONT_PAGE_SIZE_COUNT,
+ };
+
+ // a single character in the cache
+ typedef unsigned short HCacheEntry;
+ struct CacheEntry_t
+ {
+ vgui::HFont font;
+ wchar_t wch;
+ unsigned char page;
+ float texCoords[4];
+
+ // doubly-linked list for use in the LRU
+ HCacheEntry nextEntry;
+ HCacheEntry prevEntry;
+ };
+
+ // a single texture page
+ struct Page_t
+ {
+ short textureID[vgui::FONT_DRAW_TYPE_COUNT];
+ short maxFontHeight;
+ short tallestCharOnLine;
+ short wide, tall; // total size of the page
+ short nextX, nextY; // position to draw any new character positions
+ };
+
+ // allocates a new page for a given character
+ bool AllocatePageForChar(int charWide, int charTall, int &pageIndex, int &drawX, int &drawY, int &twide, int &ttall);
+
+ // Creates font materials
+ void CreateFontMaterials( Page_t &page, ITexture *pFontTexture, bool bitmapFont = false );
+
+ // Computes the page size given a character height
+ int ComputePageType( int charTall ) const;
+
+ static bool CacheEntryLessFunc(const CacheEntry_t &lhs, const CacheEntry_t &rhs);
+
+ CUtlRBTree<CacheEntry_t, HCacheEntry> m_CharCache;
+
+ // cache
+ typedef CUtlVector<Page_t> FontPageList_t;
+ FontPageList_t m_PageList;
+
+ int m_pCurrPage[FONT_PAGE_SIZE_COUNT];
+ HCacheEntry m_LRUListHeadIndex;
+ static int s_pFontPageSize[FONT_PAGE_SIZE_COUNT];
+ CUtlMap< vgui::HFont, Page_t > m_FontPages;
+};
+
+
+#endif // FONTTEXTURECACHE_H
diff --git a/vguimatsurface/Input.cpp b/vguimatsurface/Input.cpp
new file mode 100644
index 0000000..cafacce
--- /dev/null
+++ b/vguimatsurface/Input.cpp
@@ -0,0 +1,524 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implementation of the VGUI ISurface interface using the
+// material system to implement it
+//
+//===========================================================================//
+
+#if defined( WIN32 ) && !defined( _X360 )
+#include <windows.h>
+#include <zmouse.h>
+#endif
+#include "inputsystem/iinputsystem.h"
+#include "tier2/tier2.h"
+#include "Input.h"
+#include "vguimatsurface.h"
+#include "../vgui2/src/VPanel.h"
+#include <vgui/KeyCode.h>
+#include <vgui/MouseCode.h>
+#include <vgui/IVGui.h>
+#include <vgui/IPanel.h>
+#include <vgui/ISurface.h>
+#include <vgui/IClientPanel.h>
+#include "inputsystem/ButtonCode.h"
+#include "Cursor.h"
+#include "tier0/dbg.h"
+#include "../vgui2/src/vgui_key_translation.h"
+#include <vgui/IInputInternal.h>
+#include "tier0/icommandline.h"
+#ifdef _X360
+#include "xbox/xbox_win32stubs.h"
+#endif
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// Vgui input events
+//-----------------------------------------------------------------------------
+enum VguiInputEventType_t
+{
+ IE_Close = IE_FirstVguiEvent,
+ IE_LocateMouseClick,
+ IE_SetCursor,
+ IE_KeyTyped,
+ IE_KeyCodeTyped,
+ IE_InputLanguageChanged,
+ IE_IMESetWindow,
+ IE_IMEStartComposition,
+ IE_IMEComposition,
+ IE_IMEEndComposition,
+ IE_IMEShowCandidates,
+ IE_IMEChangeCandidates,
+ IE_IMECloseCandidates,
+ IE_IMERecomputeModes,
+};
+
+void InitInput()
+{
+ EnableInput( true );
+}
+
+
+static bool s_bInputEnabled = true;
+#ifdef WIN32
+//-----------------------------------------------------------------------------
+// Translates actual keys into VGUI ids
+//-----------------------------------------------------------------------------
+static WNDPROC s_ChainedWindowProc = NULL;
+extern HWND thisWindow;
+
+
+//-----------------------------------------------------------------------------
+// Initializes the input system
+//-----------------------------------------------------------------------------
+
+static bool s_bIMEComposing = false;
+static HWND s_hLastHWnd = 0;
+
+
+//-----------------------------------------------------------------------------
+// Handles input messages
+//-----------------------------------------------------------------------------
+static LRESULT CALLBACK MatSurfaceWindowProc( HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam )
+{
+ if ( !s_bInputEnabled )
+ goto chainWndProc;
+
+ InputEvent_t event;
+ memset( &event, 0, sizeof(event) );
+ event.m_nTick = g_pInputSystem->GetPollTick();
+
+ if ( hwnd != s_hLastHWnd )
+ {
+ s_hLastHWnd = hwnd;
+ event.m_nType = IE_IMESetWindow;
+ event.m_nData = (int)s_hLastHWnd;
+ g_pInputSystem->PostUserEvent( event );
+ }
+
+ switch(uMsg)
+ {
+ case WM_QUIT:
+ // According to windows docs, WM_QUIT should never be passed to wndprocs
+ Assert( 0 );
+ break;
+
+ case WM_CLOSE:
+ // Handle close messages
+ {
+ LONG_PTR wndProc = GetWindowLongPtrW( hwnd, GWLP_WNDPROC );
+ if ( wndProc == (LONG_PTR)MatSurfaceWindowProc )
+ {
+ event.m_nType = IE_Close;
+ g_pInputSystem->PostUserEvent( event );
+ }
+ }
+ return 0;
+
+ // All mouse messages need to mark where the click occurred before chaining down
+ case WM_LBUTTONDOWN:
+ case WM_RBUTTONDOWN:
+ case WM_MBUTTONDOWN:
+ case MS_WM_XBUTTONDOWN:
+ case WM_LBUTTONUP:
+ case WM_RBUTTONUP:
+ case WM_MBUTTONUP:
+ case MS_WM_XBUTTONUP:
+ case WM_LBUTTONDBLCLK:
+ case WM_RBUTTONDBLCLK:
+ case WM_MBUTTONDBLCLK:
+ case MS_WM_XBUTTONDBLCLK:
+ event.m_nType = IE_LocateMouseClick;
+ event.m_nData = (short)LOWORD(lParam);
+ event.m_nData2 = (short)HIWORD(lParam);
+ g_pInputSystem->PostUserEvent( event );
+ break;
+
+ case WM_SETCURSOR:
+ event.m_nType = IE_SetCursor;
+ g_pInputSystem->PostUserEvent( event );
+ break;
+
+ case WM_XCONTROLLER_KEY:
+ if ( IsX360() )
+ {
+ // First have to insert the edge case event
+ int nRetVal = 0;
+ if ( s_ChainedWindowProc )
+ {
+ nRetVal = CallWindowProcW( s_ChainedWindowProc, hwnd, uMsg, wParam, lParam );
+ }
+
+ // xboxissue - as yet HL2 input hasn't been made aware of analog inputs or ports
+ // so just digital step on the sample range
+ int sample = LOWORD( lParam );
+ if ( sample )
+ {
+ event.m_nType = IE_KeyCodeTyped;
+ event.m_nData = (vgui::KeyCode)wParam;
+ g_pInputSystem->PostUserEvent( event );
+ }
+ }
+ break;
+
+ // Need to deal with key repeat for keydown since inputsystem doesn't
+ case WM_KEYDOWN:
+ case WM_SYSKEYDOWN:
+ {
+ // First have to insert the edge case event
+ int nRetVal = 0;
+ if ( s_ChainedWindowProc )
+ {
+ nRetVal = CallWindowProcW( s_ChainedWindowProc, hwnd, uMsg, wParam, lParam );
+ }
+
+ int nKeyRepeat = LOWORD( lParam );
+ for ( int i = 0; i < nKeyRepeat; ++i )
+ {
+ event.m_nType = IE_KeyCodeTyped;
+ event.m_nData = KeyCode_VirtualKeyToVGUI( wParam );
+ g_pInputSystem->PostUserEvent( event );
+ }
+
+ return nRetVal;
+ }
+
+ case WM_SYSCHAR:
+ case WM_CHAR:
+ if ( !s_bIMEComposing )
+ {
+ event.m_nType = IE_KeyTyped;
+ event.m_nData = (int)wParam;
+ g_pInputSystem->PostUserEvent( event );
+ }
+ break;
+
+ case WM_INPUTLANGCHANGE:
+ event.m_nType = IE_InputLanguageChanged;
+ g_pInputSystem->PostUserEvent( event );
+ break;
+
+ case WM_IME_STARTCOMPOSITION:
+ s_bIMEComposing = true;
+ event.m_nType = IE_IMEStartComposition;
+ g_pInputSystem->PostUserEvent( event );
+ return TRUE;
+
+ case WM_IME_COMPOSITION:
+ event.m_nType = IE_IMEComposition;
+ event.m_nData = (int)lParam;
+ g_pInputSystem->PostUserEvent( event );
+ return TRUE;
+
+ case WM_IME_ENDCOMPOSITION:
+ s_bIMEComposing = false;
+ event.m_nType = IE_IMEEndComposition;
+ g_pInputSystem->PostUserEvent( event );
+ return TRUE;
+
+ case WM_IME_NOTIFY:
+ {
+ switch (wParam)
+ {
+ default:
+ break;
+
+ case 14: // Chinese Traditional IMN_PRIVATE...
+ break;
+
+ case IMN_OPENCANDIDATE:
+ event.m_nType = IE_IMEShowCandidates;
+ g_pInputSystem->PostUserEvent( event );
+ return 1;
+
+ case IMN_CHANGECANDIDATE:
+ event.m_nType = IE_IMEChangeCandidates;
+ g_pInputSystem->PostUserEvent( event );
+ return 0;
+
+ case IMN_CLOSECANDIDATE:
+ event.m_nType = IE_IMECloseCandidates;
+ g_pInputSystem->PostUserEvent( event );
+ break;
+
+ // To detect the change of IME mode, or the toggling of Japanese IME
+ case IMN_SETCONVERSIONMODE:
+ case IMN_SETSENTENCEMODE:
+ case IMN_SETOPENSTATUS:
+ event.m_nType = IE_IMERecomputeModes;
+ g_pInputSystem->PostUserEvent( event );
+ if ( wParam == IMN_SETOPENSTATUS )
+ return 0;
+ break;
+
+ case IMN_CLOSESTATUSWINDOW:
+ case IMN_GUIDELINE:
+ case IMN_OPENSTATUSWINDOW:
+ case IMN_SETCANDIDATEPOS:
+ case IMN_SETCOMPOSITIONFONT:
+ case IMN_SETCOMPOSITIONWINDOW:
+ case IMN_SETSTATUSWINDOWPOS:
+ break;
+ }
+ }
+
+ case WM_IME_SETCONTEXT:
+ // We draw all IME windows ourselves
+ lParam &= ~ISC_SHOWUICOMPOSITIONWINDOW;
+ lParam &= ~ISC_SHOWUIGUIDELINE;
+ lParam &= ~ISC_SHOWUIALLCANDIDATEWINDOW;
+ break;
+
+ case WM_IME_CHAR:
+ // We need to process this message so that the IME doesn't double convert the unicode IME characters into garbage characters and post
+ // them to our window... (get ? marks after text entry ).
+ return 0;
+ }
+
+chainWndProc:
+ if ( s_ChainedWindowProc )
+ return CallWindowProcW( s_ChainedWindowProc, hwnd, uMsg, wParam, lParam );
+
+ // This means the application is driving the messages (calling our window procedure manually)
+ // rather than us hooking their window procedure. The engine needs to do this in order for VCR
+ // mode to play back properly.
+ return 0;
+}
+
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Enables/disables input (enabled by default)
+//-----------------------------------------------------------------------------
+void EnableInput( bool bEnable )
+{
+#if 0 // #ifdef BENCHMARK
+ s_bInputEnabled = false;
+#else
+ s_bInputEnabled = bEnable;
+#endif
+}
+
+
+#ifdef WIN32
+//-----------------------------------------------------------------------------
+// Hooks input listening up to a window
+//-----------------------------------------------------------------------------
+void InputAttachToWindow(void *hwnd)
+{
+#if !defined( USE_SDL )
+ s_ChainedWindowProc = (WNDPROC)GetWindowLongPtrW( (HWND)hwnd, GWLP_WNDPROC );
+ SetWindowLongPtrW( (HWND)hwnd, GWLP_WNDPROC, (LONG_PTR)MatSurfaceWindowProc );
+#endif
+}
+
+void InputDetachFromWindow(void *hwnd)
+{
+ if (!hwnd)
+ return;
+ if ( s_ChainedWindowProc )
+ {
+ SetWindowLongPtrW( (HWND)hwnd, GWLP_WNDPROC, (LONG_PTR) s_ChainedWindowProc );
+ s_ChainedWindowProc = NULL;
+ }
+}
+#else
+void InputAttachToWindow(void *hwnd)
+{
+#if !defined( OSX ) && !defined( LINUX )
+ if ( hwnd && !HushAsserts() )
+ {
+ // under OSX we use the Cocoa mgr to route events rather than hooking winprocs
+ // and under Linux we use SDL
+ Assert( !"Implement me" );
+ }
+#endif
+}
+
+void InputDetachFromWindow(void *hwnd)
+{
+#if !defined( OSX ) && !defined( LINUX )
+ if ( hwnd && !HushAsserts() )
+ {
+ // under OSX we use the Cocoa mgr to route events rather than hooking winprocs
+ // and under Linux we use SDL
+ Assert( !"Implement me" );
+ }
+#endif
+}
+#endif
+
+
+//-----------------------------------------------------------------------------
+// Converts an input system button code to a vgui key code
+// FIXME: Remove notion of vgui::KeyCode + vgui::MouseCode altogether
+//-----------------------------------------------------------------------------
+static vgui::KeyCode ButtonCodeToKeyCode( ButtonCode_t buttonCode )
+{
+ return ( vgui::KeyCode )buttonCode;
+}
+
+static vgui::MouseCode ButtonCodeToMouseCode( ButtonCode_t buttonCode )
+{
+ return ( vgui::MouseCode )buttonCode;
+}
+
+
+//-----------------------------------------------------------------------------
+// Handles an input event, returns true if the event should be filtered
+// from the rest of the game
+//-----------------------------------------------------------------------------
+bool InputHandleInputEvent( const InputEvent_t &event )
+{
+ switch( event.m_nType )
+ {
+ case IE_ButtonPressed:
+ {
+ // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
+ ButtonCode_t code = (ButtonCode_t)event.m_nData2;
+ if ( IsKeyCode( code ) || IsJoystickCode( code ) )
+ {
+ vgui::KeyCode keyCode = ButtonCodeToKeyCode( code );
+ return g_pIInput->InternalKeyCodePressed( keyCode );
+ }
+
+ if ( IsJoystickCode( code ) )
+ {
+ vgui::KeyCode keyCode = ButtonCodeToKeyCode( code );
+ return g_pIInput->InternalKeyCodePressed( keyCode );
+ }
+
+ if ( IsMouseCode( code ) )
+ {
+ vgui::MouseCode mouseCode = ButtonCodeToMouseCode( code );
+ return g_pIInput->InternalMousePressed( mouseCode );
+ }
+ }
+ break;
+
+ case IE_ButtonReleased:
+ {
+ // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
+ ButtonCode_t code = (ButtonCode_t)event.m_nData2;
+ if ( IsKeyCode( code ) || IsJoystickCode( code ) )
+ {
+ vgui::KeyCode keyCode = ButtonCodeToKeyCode( code );
+ return g_pIInput->InternalKeyCodeReleased( keyCode );
+ }
+
+ if ( IsJoystickCode( code ) )
+ {
+ vgui::KeyCode keyCode = ButtonCodeToKeyCode( code );
+ return g_pIInput->InternalKeyCodeReleased( keyCode );
+ }
+
+ if ( IsMouseCode( code ) )
+ {
+ vgui::MouseCode mouseCode = ButtonCodeToMouseCode( code );
+ return g_pIInput->InternalMouseReleased( mouseCode );
+ }
+ }
+ break;
+
+ case IE_ButtonDoubleClicked:
+ {
+ // NOTE: data2 is the virtual key code (data1 contains the scan-code one)
+ ButtonCode_t code = (ButtonCode_t)event.m_nData2;
+ if ( IsMouseCode( code ) )
+ {
+ vgui::MouseCode mouseCode = ButtonCodeToMouseCode( code );
+ return g_pIInput->InternalMouseDoublePressed( mouseCode );
+ }
+ }
+ break;
+
+ case IE_AnalogValueChanged:
+ {
+ if ( event.m_nData == MOUSE_WHEEL )
+ return g_pIInput->InternalMouseWheeled( event.m_nData3 );
+ if ( event.m_nData == MOUSE_XY )
+ return g_pIInput->InternalCursorMoved( event.m_nData2, event.m_nData3 );
+ }
+ break;
+
+ case IE_KeyCodeTyped:
+ {
+ vgui::KeyCode code = (vgui::KeyCode)event.m_nData;
+ g_pIInput->InternalKeyCodeTyped( code );
+ }
+ return true;
+
+ case IE_KeyTyped:
+ {
+ vgui::KeyCode code = (vgui::KeyCode)event.m_nData;
+ g_pIInput->InternalKeyTyped( code );
+ }
+ return true;
+
+ case IE_Quit:
+ g_pVGui->Stop();
+#if defined( USE_SDL )
+ return false; // also let higher layers consume it
+#else
+ return true;
+#endif
+
+ case IE_Close:
+ // FIXME: Change this so we don't stop until 'save' occurs, etc.
+ g_pVGui->Stop();
+ return true;
+
+ case IE_SetCursor:
+ ActivateCurrentCursor();
+ return true;
+
+ case IE_IMESetWindow:
+ g_pIInput->SetIMEWindow( (void *)event.m_nData );
+ return true;
+
+ case IE_LocateMouseClick:
+ g_pIInput->InternalCursorMoved( event.m_nData, event.m_nData2 );
+ return true;
+
+ case IE_InputLanguageChanged:
+ g_pIInput->OnInputLanguageChanged();
+ return true;
+
+ case IE_IMEStartComposition:
+ g_pIInput->OnIMEStartComposition();
+ return true;
+
+ case IE_IMEComposition:
+ g_pIInput->OnIMEComposition( event.m_nData );
+ return true;
+
+ case IE_IMEEndComposition:
+ g_pIInput->OnIMEEndComposition();
+ return true;
+
+ case IE_IMEShowCandidates:
+ g_pIInput->OnIMEShowCandidates();
+ return true;
+
+ case IE_IMEChangeCandidates:
+ g_pIInput->OnIMEChangeCandidates();
+ return true;
+
+ case IE_IMECloseCandidates:
+ g_pIInput->OnIMECloseCandidates();
+ return true;
+
+ case IE_IMERecomputeModes:
+ g_pIInput->OnIMERecomputeModes();
+ return true;
+ }
+
+ return false;
+}
+
+
+
diff --git a/vguimatsurface/Input.h b/vguimatsurface/Input.h
new file mode 100644
index 0000000..0f45cae
--- /dev/null
+++ b/vguimatsurface/Input.h
@@ -0,0 +1,47 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Methods related to input
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef INPUT_H
+#define INPUT_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+struct InputEvent_t;
+
+
+//-----------------------------------------------------------------------------
+// Initializes the input system
+//-----------------------------------------------------------------------------
+void InitInput();
+
+
+//-----------------------------------------------------------------------------
+// Hooks input listening up to a window
+//-----------------------------------------------------------------------------
+void InputAttachToWindow(void *hwnd);
+void InputDetachFromWindow(void *hwnd);
+
+// If input isn't hooked, this forwards messages to vgui.
+void InputHandleWindowMessage( void *hwnd, unsigned int uMsg, unsigned int wParam, long lParam );
+
+//-----------------------------------------------------------------------------
+// Handles an input event, returns true if the event should be filtered
+// from the rest of the game
+//-----------------------------------------------------------------------------
+bool InputHandleInputEvent( const InputEvent_t &event );
+
+
+//-----------------------------------------------------------------------------
+// Enables/disables input (enabled by default)
+//-----------------------------------------------------------------------------
+void EnableInput( bool bEnable );
+
+
+#endif // INPUT_H \ No newline at end of file
diff --git a/vguimatsurface/MatSystemSurface.cpp b/vguimatsurface/MatSystemSurface.cpp
new file mode 100644
index 0000000..7426590
--- /dev/null
+++ b/vguimatsurface/MatSystemSurface.cpp
@@ -0,0 +1,4614 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implementation of the VGUI ISurface interface using the
+// material system to implement it
+//
+//=============================================================================//
+
+#if defined( WIN32) && !defined( _X360 )
+#include <windows.h>
+#endif
+#ifdef OSX
+#include <Carbon/Carbon.h>
+#endif
+
+#if defined( USE_SDL )
+#include <appframework/ilaunchermgr.h>
+ILauncherMgr *g_pLauncherMgr = NULL;
+#endif
+
+
+#include "tier1/strtools.h"
+#include "tier0/icommandline.h"
+#include "tier0/dbg.h"
+#include "filesystem.h"
+#include <vgui/VGUI.h>
+#include <Color.h>
+#include "utlbuffer.h"
+#include "utlvector.h"
+#include "Clip2D.h"
+#include <vgui_controls/Panel.h>
+#include <vgui/IInput.h>
+#include <vgui/Point.h>
+#include "bitmap/imageformat.h"
+#include "TextureDictionary.h"
+#include "Cursor.h"
+#include "Input.h"
+#include <vgui/IHTML.h>
+#include <vgui/IVGui.h>
+#include "vgui_surfacelib/FontManager.h"
+#include "FontTextureCache.h"
+#include "MatSystemSurface.h"
+#include "inputsystem/iinputsystem.h"
+#include <vgui_controls/Controls.h>
+#include <vgui/ISystem.h>
+#include "icvar.h"
+#include "mathlib/mathlib.h"
+#include <vgui/ILocalize.h>
+#include "mathlib/vmatrix.h"
+#include <tier0/vprof.h>
+#include "materialsystem/itexture.h"
+#include <malloc.h>
+#include "../vgui2/src/VPanel.h"
+#include <vgui/IInputInternal.h>
+#if defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#endif
+#include "xbox/xboxstubs.h"
+#include "../vgui2/src/Memorybitmap.h"
+
+#pragma warning( disable : 4706 )
+
+#include <vgui/IVguiMatInfo.h>
+#include <vgui/IVguiMatInfoVar.h>
+#include "materialsystem/imaterialvar.h"
+
+#pragma warning( default : 4706 )
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+
+
+#define VPANEL_NORMAL ((vgui::SurfacePlat *) NULL)
+#define VPANEL_MINIMIZED ((vgui::SurfacePlat *) 0x00000001)
+
+using namespace vgui;
+
+static bool g_bSpewFocus = false;
+
+class CVguiMatInfoVar : public IVguiMatInfoVar
+{
+public:
+ CVguiMatInfoVar( IMaterialVar *pMaterialVar )
+ {
+ m_pMaterialVar = pMaterialVar;
+ }
+
+ // from IVguiMatInfoVar
+ virtual int GetIntValue ( void ) const
+ {
+ return m_pMaterialVar->GetIntValue();
+ }
+
+ virtual void SetIntValue ( int val )
+ {
+ m_pMaterialVar->SetIntValue( val );
+ }
+
+private:
+ IMaterialVar *m_pMaterialVar;
+};
+
+class CVguiMatInfo : public IVguiMatInfo
+{
+public:
+ CVguiMatInfo( IMaterial *pMaterial )
+ {
+ m_pMaterial = pMaterial;
+ }
+
+ // from IVguiMatInfo
+ virtual IVguiMatInfoVar* FindVarFactory( const char *varName, bool *found )
+ {
+ IMaterialVar *pMaterialVar = m_pMaterial->FindVar( varName, found );
+
+ if ( pMaterialVar == NULL )
+ return NULL;
+ return new CVguiMatInfoVar( pMaterialVar );
+ }
+
+ virtual int GetNumAnimationFrames( void )
+ {
+ return m_pMaterial->GetNumAnimationFrames();
+ }
+
+private:
+ IMaterial *m_pMaterial;
+};
+
+
+//-----------------------------------------------------------------------------
+// Globals...
+//-----------------------------------------------------------------------------
+vgui::IInputInternal *g_pIInput;
+static bool g_bInDrawing;
+static CFontTextureCache g_FontTextureCache;
+
+//-----------------------------------------------------------------------------
+// Singleton instance
+//-----------------------------------------------------------------------------
+CMatSystemSurface g_MatSystemSurface;
+EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CMatSystemSurface, ISurface,
+ VGUI_SURFACE_INTERFACE_VERSION, g_MatSystemSurface );
+
+#ifdef LINUX
+CUtlDict< CMatSystemSurface::font_entry, unsigned short > CMatSystemSurface::m_FontData;
+#endif
+
+//-----------------------------------------------------------------------------
+// Make sure the panel is the same size as the viewport
+//-----------------------------------------------------------------------------
+CMatEmbeddedPanel::CMatEmbeddedPanel() : BaseClass( NULL, "MatSystemTopPanel" )
+{
+ SetPaintBackgroundEnabled( false );
+
+#if defined( _X360 )
+ SetPos( 0, 0 );
+ SetSize( GetSystemMetrics( SM_CXSCREEN ), GetSystemMetrics( SM_CYSCREEN ) );
+#endif
+}
+
+void CMatEmbeddedPanel::OnThink()
+{
+ int x, y, width, height;
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ pRenderContext->GetViewport( x, y, width, height );
+ SetSize( width, height );
+ SetPos( x, y );
+ Repaint();
+}
+
+VPANEL CMatEmbeddedPanel::IsWithinTraverse(int x, int y, bool traversePopups)
+{
+ VPANEL retval = BaseClass::IsWithinTraverse( x, y, traversePopups );
+ if ( retval == GetVPanel() )
+ return 0;
+ return retval;
+}
+
+
+//-----------------------------------------------------------------------------
+// Constructor, destructor
+//-----------------------------------------------------------------------------
+CMatSystemSurface::CMatSystemSurface() : m_pEmbeddedPanel(NULL), m_pWhite(NULL)
+{
+ m_iBoundTexture = -1;
+ m_HWnd = NULL;
+ m_bIn3DPaintMode = false;
+ m_b3DPaintRenderToTexture = false;
+ m_bDrawingIn3DWorld = false;
+ m_PlaySoundFunc = NULL;
+ m_bInThink = false;
+ m_bAllowJavaScript = false;
+ m_bAppDrivesInput = false;
+ m_nLastInputPollCount = 0;
+
+ m_hCurrentFont = NULL;
+ m_pRestrictedPanel = NULL;
+
+ m_bNeedsKeyboard = true;
+ m_bNeedsMouse = true;
+ m_bUsingTempFullScreenBufferMaterial = false;
+ m_nFullScreenBufferMaterialId = -1;
+
+ memset( m_WorkSpaceInsets, 0, sizeof( m_WorkSpaceInsets ) );
+ m_nBatchedCharVertCount = 0;
+
+ m_nFullscreenViewportX = m_nFullscreenViewportY = 0;
+ m_nFullscreenViewportWidth = m_nFullscreenViewportHeight = 0;
+ m_pFullscreenRenderTarget = NULL;
+
+ m_cursorAlwaysVisible = false;
+}
+
+CMatSystemSurface::~CMatSystemSurface()
+{
+ if ( m_nFullScreenBufferMaterialId != -1 )
+ {
+ DestroyTextureID( m_nFullScreenBufferMaterialId );
+ m_nFullScreenBufferMaterialId = -1;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Connect, disconnect...
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::Connect( CreateInterfaceFn factory )
+{
+ if ( !BaseClass::Connect( factory ) )
+ return false;
+
+ if ( !g_pFullFileSystem )
+ {
+ Warning( "MatSystemSurface requires the file system to run!\n" );
+ return false;
+ }
+
+ if ( !g_pMaterialSystem )
+ {
+ Warning( "MatSystemSurface requires the material system to run!\n" );
+ return false;
+ }
+
+ if ( !g_pVGuiPanel )
+ {
+ Warning( "MatSystemSurface requires the vgui::IPanel system to run!\n" );
+ return false;
+ }
+
+ g_pIInput = (IInputInternal *)factory( VGUI_INPUTINTERNAL_INTERFACE_VERSION, NULL );
+ if ( !g_pIInput )
+ {
+ Warning( "MatSystemSurface requires the vgui::IInput system to run!\n" );
+ return false;
+ }
+
+ if ( !g_pVGui )
+ {
+ Warning( "MatSystemSurface requires the vgui::IVGUI system to run!\n" );
+ return false;
+ }
+
+ Assert( g_pVGuiSurface == this );
+
+ // initialize vgui_control interfaces
+ if ( !vgui::VGui_InitInterfacesList( "MATSURFACE", &factory, 1 ) )
+ return false;
+
+#ifdef USE_SDL
+ g_pLauncherMgr = (ILauncherMgr *)factory( SDLMGR_INTERFACE_VERSION, NULL );
+#endif
+
+ return true;
+}
+
+void CMatSystemSurface::Disconnect()
+{
+ g_pIInput = NULL;
+ BaseClass::Disconnect();
+}
+
+
+//-----------------------------------------------------------------------------
+// Access to other interfaces...
+//-----------------------------------------------------------------------------
+void *CMatSystemSurface::QueryInterface( const char *pInterfaceName )
+{
+ // We also implement the IMatSystemSurface interface
+ if (!Q_strncmp( pInterfaceName, MAT_SYSTEM_SURFACE_INTERFACE_VERSION, Q_strlen(MAT_SYSTEM_SURFACE_INTERFACE_VERSION) + 1))
+ return (IMatSystemSurface*)this;
+
+ // We also implement the IMatSystemSurface interface
+ if (!Q_strncmp( pInterfaceName, VGUI_SURFACE_INTERFACE_VERSION, Q_strlen(VGUI_SURFACE_INTERFACE_VERSION) + 1))
+ return (vgui::ISurface*)this;
+
+ return BaseClass::QueryInterface( pInterfaceName );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InitFullScreenBuffer( const char *pszRenderTargetName )
+{
+ if ( !IsPC() )
+ return;
+
+ char pTemp[512];
+ Q_snprintf( pTemp, sizeof(pTemp), "VGUI_3DPaint_FullScreen_%s", pszRenderTargetName );
+ m_FullScreenBufferMaterial.Shutdown();
+
+ // Set up a material with which to reference the final image for subsequent display using vgui
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetString( "$basetexture", pszRenderTargetName );
+ pVMTKeyValues->SetInt( "$nocull", 1 );
+ pVMTKeyValues->SetInt( "$nofog", 1 );
+ pVMTKeyValues->SetInt( "$ignorez", 1 );
+ pVMTKeyValues->SetInt( "$translucent", 1 );
+ m_FullScreenBufferMaterial.Init( pTemp, TEXTURE_GROUP_OTHER, pVMTKeyValues );
+ m_FullScreenBufferMaterial->Refresh();
+
+ if ( m_nFullScreenBufferMaterialId != -1 )
+ {
+ DestroyTextureID( m_nFullScreenBufferMaterialId );
+ }
+ m_nFullScreenBufferMaterialId = -1;
+ m_FullScreenBuffer.Shutdown();
+
+ m_FullScreenBufferName = pszRenderTargetName;
+}
+
+//-----------------------------------------------------------------------------
+// Initialization and shutdown...
+//-----------------------------------------------------------------------------
+InitReturnVal_t CMatSystemSurface::Init( void )
+{
+ InitReturnVal_t nRetVal = BaseClass::Init();
+ if ( nRetVal != INIT_OK )
+ return nRetVal;
+
+ // Allocate a white material
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetInt( "$vertexcolor", 1 );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$ignorez", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+
+ if ( ! (CommandLine()->FindParm("-disable_matsurf_noculls")) )
+ {
+ pVMTKeyValues->SetInt( "$nocull", 1 ); // skip this if user asks for the switch above
+ }
+
+ m_pWhite.Init( "VGUI_White", TEXTURE_GROUP_OTHER, pVMTKeyValues );
+
+ InitFullScreenBuffer( "_rt_FullScreen" );
+
+ m_DrawColor[0] = m_DrawColor[1] = m_DrawColor[2] = m_DrawColor[3] = 255;
+ m_nTranslateX = m_nTranslateY = 0;
+ EnableScissor( false );
+ SetScissorRect( 0, 0, 100000, 100000 );
+ m_flAlphaMultiplier = 1.0f;
+
+ // By default, use the default embedded panel
+ m_pDefaultEmbeddedPanel = new CMatEmbeddedPanel;
+ SetEmbeddedPanel( m_pDefaultEmbeddedPanel->GetVPanel() );
+
+ m_iBoundTexture = -1;
+
+ // Initialize font info..
+ m_pDrawTextPos[0] = m_pDrawTextPos[1] = 0;
+ m_DrawTextColor[0] = m_DrawTextColor[1] = m_DrawTextColor[2] = m_DrawTextColor[3] = 255;
+
+ m_bIn3DPaintMode = false;
+ m_b3DPaintRenderToTexture = false;
+ m_bDrawingIn3DWorld = false;
+ m_PlaySoundFunc = NULL;
+
+ // Input system
+ InitInput();
+
+ // Initialize cursors
+ InitCursors();
+
+ // fonts initialization
+ char language[64];
+ bool bValid;
+ if ( IsPC() )
+ {
+ bValid = system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Source\\Language", language, sizeof(language)-1 );
+ }
+ else
+ {
+ Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
+ bValid = true;
+ }
+
+ if ( bValid )
+ {
+ FontManager().SetLanguage( language );
+ }
+ else
+ {
+ FontManager().SetLanguage( "english" );
+ }
+
+#ifdef LINUX
+ FontManager().SetFontDataHelper( &CMatSystemSurface::FontDataHelper );
+#endif
+
+ // font manager needs the file system and material system for bitmap fonts
+ FontManager().SetInterfaces( g_pFullFileSystem, g_pMaterialSystem );
+
+ g_bSpewFocus = CommandLine()->FindParm( "-vguifocus" ) ? true : false;
+
+ return INIT_OK;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::Shutdown( void )
+{
+ for ( int i = m_FileTypeImages.First(); i != m_FileTypeImages.InvalidIndex(); i = m_FileTypeImages.Next( i ) )
+ {
+ delete m_FileTypeImages[ i ];
+ }
+ m_FileTypeImages.RemoveAll();
+
+ // Release all textures
+ TextureDictionary()->DestroyAllTextures();
+ m_iBoundTexture = -1;
+
+ // Release the standard materials
+ m_pWhite.Shutdown();
+ m_FullScreenBufferMaterial.Shutdown();
+ m_FullScreenBuffer.Shutdown();
+
+ m_Titles.Purge();
+ m_PaintStateStack.Purge();
+
+#if defined( WIN32 ) && !defined( _X360 )
+ // release any custom font files
+ // use newer function if possible
+ HMODULE gdiModule = ::LoadLibrary( "gdi32.dll" );
+ typedef int (WINAPI *RemoveFontResourceExProc)(LPCTSTR, DWORD, PVOID);
+ RemoveFontResourceExProc pRemoveFontResourceEx = NULL;
+ if ( gdiModule )
+ {
+ pRemoveFontResourceEx = (RemoveFontResourceExProc)::GetProcAddress(gdiModule, "RemoveFontResourceExA");
+ }
+
+ for (int i = 0; i < m_CustomFontFileNames.Count(); i++)
+ {
+ if (pRemoveFontResourceEx)
+ {
+ // dvs: Keep removing the font until we get an error back. After consulting with Microsoft, it appears
+ // that RemoveFontResourceEx must sometimes be called multiple times to work. Doing this insures that
+ // when we load the font next time we get the real font instead of Ariel.
+ int nRetries = 0;
+ while ( (*pRemoveFontResourceEx)(m_CustomFontFileNames[i].String(), 0x10, NULL) && ( nRetries < 10 ) )
+ {
+ nRetries++;
+ Msg( "Removed font resource %s on attempt %d.\n", m_CustomFontFileNames[i].String(), nRetries );
+ }
+ }
+ else
+ {
+ // dvs: Keep removing the font until we get an error back. After consulting with Microsoft, it appears
+ // that RemoveFontResourceEx must sometimes be called multiple times to work. Doing this insures that
+ // when we load the font next time we get the real font instead of Ariel.
+ int nRetries = 0;
+ while ( ::RemoveFontResource(m_CustomFontFileNames[i].String()) && ( nRetries < 10 ) )
+ {
+ nRetries++;
+ Msg( "Removed font resource %s on attempt %d.\n", m_CustomFontFileNames[i].String(), nRetries );
+ }
+ }
+ }
+#endif
+
+ m_CustomFontFileNames.RemoveAll();
+ m_BitmapFontFileNames.RemoveAll();
+ m_BitmapFontFileMapping.RemoveAll();
+
+ Cursor_ClearUserCursors();
+
+#if defined( WIN32 ) && !defined( _X360 )
+ if ( gdiModule )
+ {
+ ::FreeLibrary(gdiModule);
+ }
+#endif
+
+ BaseClass::Shutdown();
+}
+
+void CMatSystemSurface::SetEmbeddedPanel(VPANEL pEmbeddedPanel)
+{
+ m_pEmbeddedPanel = pEmbeddedPanel;
+ ((VPanel *)pEmbeddedPanel)->Client()->RequestFocus(0);
+}
+
+//-----------------------------------------------------------------------------
+// hierarchy root
+//-----------------------------------------------------------------------------
+VPANEL CMatSystemSurface::GetEmbeddedPanel()
+{
+ return m_pEmbeddedPanel;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: cap bits
+// Warning: if you change this, make sure the SurfaceV28 wrapper above reports
+// the correct capabilities.
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::SupportsFeature(SurfaceFeature_e feature)
+{
+ switch (feature)
+ {
+ case ISurface::ANTIALIASED_FONTS:
+ case ISurface::DROPSHADOW_FONTS:
+ return true;
+
+ case ISurface::OUTLINE_FONTS:
+ if ( IsX360() )
+ return false;
+ return true;
+
+ case ISurface::ESCAPE_KEY:
+ return true;
+
+ case ISurface::OPENING_NEW_HTML_WINDOWS:
+ case ISurface::FRAME_MINIMIZE_MAXIMIZE:
+ default:
+ return false;
+ };
+}
+
+//-----------------------------------------------------------------------------
+// Hook needed to Get input to work
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::AttachToWindow( void *hWnd, bool bLetAppDriveInput )
+{
+ InputDetachFromWindow( m_HWnd );
+ m_HWnd = hWnd;
+ if ( hWnd )
+ {
+ InputAttachToWindow( hWnd );
+ m_bAppDrivesInput = bLetAppDriveInput;
+ }
+ else
+ {
+ // Never call RunFrame stuff
+ m_bAppDrivesInput = true;
+ }
+}
+
+bool CMatSystemSurface::HandleInputEvent( const InputEvent_t &event )
+{
+ if ( !m_bAppDrivesInput )
+ {
+ g_pIInput->UpdateButtonState( event );
+ }
+
+ return InputHandleInputEvent( event );
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a panel in 3D space. Assumes view + projection are already set up
+// Also assumes the (x,y) coordinates of the panels are defined in 640xN coords
+// (N isn't necessary 480 because the panel may not be 4x3)
+// The width + height specified are the size of the panel in world coordinates
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int pw, int ph, float sw, float sh )
+{
+ Assert( pRootPanel );
+
+ // FIXME: When should such panels be solved?!?
+ SolveTraverse( pRootPanel, false );
+
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+
+ // Force Z buffering to be on for all panels drawn...
+ pRenderContext->OverrideDepthEnable( true, false );
+
+ Assert(!m_bDrawingIn3DWorld);
+ m_bDrawingIn3DWorld = true;
+
+ StartDrawingIn3DSpace( panelCenterToWorld, pw, ph, sw, sh );
+
+ ((VPanel *)pRootPanel)->Client()->Repaint();
+ ((VPanel *)pRootPanel)->Client()->PaintTraverse(true, false);
+
+ FinishDrawing();
+
+ // Reset z buffering to normal state
+ pRenderContext->OverrideDepthEnable( false, true );
+
+ m_bDrawingIn3DWorld = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Setup rendering for vgui on a panel existing in 3D space
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::StartDrawingIn3DSpace( const VMatrix &screenToWorld, int pw, int ph, float sw, float sh )
+{
+ g_bInDrawing = true;
+ m_iBoundTexture = -1;
+
+ int px = 0;
+ int py = 0;
+
+ m_pSurfaceExtents[0] = px;
+ m_pSurfaceExtents[1] = py;
+ m_pSurfaceExtents[2] = px + pw;
+ m_pSurfaceExtents[3] = py + ph;
+
+ // In order for this to work, the model matrix must have its origin
+ // at the upper left corner of the screen. We must also scale down the
+ // rendering from pixel space to screen space. Let's construct a matrix
+ // transforming from pixel coordinates (640xN) to screen coordinates
+ // (wxh, with the origin at the upper left of the screen). Then we'll
+ // concatenate it with the panelCenterToWorld to produce pixelToWorld transform
+ VMatrix pixelToScreen;
+
+ // First, scale it so that 0->pw transforms to 0->sw
+ MatrixBuildScale( pixelToScreen, sw / pw, -sh / ph, 1.0f );
+
+ // Construct pixelToWorld
+ VMatrix pixelToWorld;
+ MatrixMultiply( screenToWorld, pixelToScreen, pixelToWorld );
+
+ // make sure there is no translation and rotation laying around
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadMatrix( pixelToWorld );
+
+ // These are only here so that FinishDrawing works...
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PushMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->PushMatrix();
+
+ // Always enable scissoring (translate to origin because of the glTranslatef call above..)
+ EnableScissor( true );
+
+ m_nTranslateX = 0;
+ m_nTranslateY = 0;
+ m_flAlphaMultiplier = 1.0f;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Setup ortho for vgui
+//-----------------------------------------------------------------------------
+
+// we may need to offset by 0.5 texels to account for the different in pixel vs. texel centers in dx7-9
+// however, we do this fixup already when we set up the texture coordinates for all materials/fonts
+// so in theory we shouldn't need to do any adjustments for setting up the screen
+// HOWEVER, we must do the offset, else the driver will think the text is something that should
+// be antialiased, so the text will look broken if antialiasing is turned on (usually forced on in the driver)
+float g_flPixelOffsetX = 0.5f;
+float g_flPixelOffsetY = 0.5f;
+
+bool g_bCheckedCommandLine = false;
+
+extern void ___stop___( void );
+void CMatSystemSurface::StartDrawing( void )
+{
+ MAT_FUNC;
+
+ if ( !g_bCheckedCommandLine )
+ {
+ g_bCheckedCommandLine = true;
+
+ const char *pX = CommandLine()->ParmValue( "-pixel_offset_x", (const char*)NULL );
+ if ( pX )
+ g_flPixelOffsetX = atof( pX );
+
+ const char *pY = CommandLine()->ParmValue( "-pixel_offset_y", (const char*)NULL );
+ if ( pY )
+ g_flPixelOffsetY = atof( pY );
+ }
+
+ g_bInDrawing = true;
+ m_iBoundTexture = -1;
+
+ int x, y, width, height;
+
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ pRenderContext->GetViewport( x, y, width, height);
+
+ // we don't want to include x and y from the viewport here. DX will
+ // automatically translate any drawing we do into that viewport.
+ m_pSurfaceExtents[0] = 0;
+ m_pSurfaceExtents[1] = 0;
+ m_pSurfaceExtents[2] = width;
+ m_pSurfaceExtents[3] = height;
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadIdentity();
+ pRenderContext->Scale( 1, -1, 1 );
+
+ //___stop___();
+ pRenderContext->Ortho( g_flPixelOffsetX, g_flPixelOffsetY, width + g_flPixelOffsetX, height + g_flPixelOffsetY, -1.0f, 1.0f );
+
+ // make sure there is no translation and rotation laying around
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadIdentity();
+
+ // Always enable scissoring (translate to origin because of the glTranslatef call above..)
+ EnableScissor( true );
+
+ m_nTranslateX = 0;
+ m_nTranslateY = 0;
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadIdentity();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::FinishDrawing( void )
+{
+ MAT_FUNC;
+
+ // We're done with scissoring
+ EnableScissor( false );
+
+ // Restore the matrices
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PopMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PopMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->PopMatrix();
+
+ Assert( g_bInDrawing );
+ g_bInDrawing = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// frame
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::RunFrame()
+{
+ int nPollCount = g_pInputSystem->GetPollCount();
+ if ( m_nLastInputPollCount == nPollCount )
+ return;
+
+ // If this isn't true, we've lost input!
+ if ( !m_bAppDrivesInput && m_nLastInputPollCount != nPollCount - 1 )
+ {
+ Assert( 0 );
+ Warning( "Vgui is losing input messages! Call brian!\n" );
+ }
+
+ m_nLastInputPollCount = nPollCount;
+
+ if ( m_bAppDrivesInput )
+ return;
+
+ // Generate all input messages
+ int nEventCount = g_pInputSystem->GetEventCount();
+ const InputEvent_t* pEvents = g_pInputSystem->GetEventData( );
+ for ( int i = 0; i < nEventCount; ++i )
+ {
+ HandleInputEvent( pEvents[i] );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets up a particular painting state...
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetupPaintState( const PaintState_t &paintState )
+{
+ m_nTranslateX = paintState.m_iTranslateX;
+ m_nTranslateY = paintState.m_iTranslateY;
+ SetScissorRect( paintState.m_iScissorLeft, paintState.m_iScissorTop,
+ paintState.m_iScissorRight, paintState.m_iScissorBottom );
+}
+
+//-----------------------------------------------------------------------------
+// Indicates a particular panel is about to be rendered
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PushMakeCurrent(VPANEL pPanel, bool useInSets)
+{
+ int inSets[4] = {0, 0, 0, 0};
+ int absExtents[4];
+ int clipRect[4];
+
+ if (useInSets)
+ {
+ g_pVGuiPanel->GetInset(pPanel, inSets[0], inSets[1], inSets[2], inSets[3]);
+ }
+
+ g_pVGuiPanel->GetAbsPos(pPanel, absExtents[0], absExtents[1]);
+ int wide, tall;
+ g_pVGuiPanel->GetSize(pPanel, wide, tall);
+ absExtents[2] = absExtents[0] + wide;
+ absExtents[3] = absExtents[1] + tall;
+
+ g_pVGuiPanel->GetClipRect(pPanel, clipRect[0], clipRect[1], clipRect[2], clipRect[3]);
+
+ int i = m_PaintStateStack.AddToTail();
+ PaintState_t &paintState = m_PaintStateStack[i];
+ paintState.m_pPanel = pPanel;
+
+ // Determine corrected top left origin
+ paintState.m_iTranslateX = inSets[0] + absExtents[0] - m_pSurfaceExtents[0];
+ paintState.m_iTranslateY = inSets[1] + absExtents[1] - m_pSurfaceExtents[1];
+
+ // Setup clipping rectangle for scissoring
+ paintState.m_iScissorLeft = clipRect[0] - m_pSurfaceExtents[0];
+ paintState.m_iScissorTop = clipRect[1] - m_pSurfaceExtents[1];
+ paintState.m_iScissorRight = clipRect[2] - m_pSurfaceExtents[0];
+ paintState.m_iScissorBottom = clipRect[3] - m_pSurfaceExtents[1];
+
+ SetupPaintState( paintState );
+}
+
+void CMatSystemSurface::PopMakeCurrent(VPANEL pPanel)
+{
+ //hushed MAT_FUNC;
+
+ // draw any remaining text
+ if ( m_nBatchedCharVertCount > 0 )
+ {
+ DrawFlushText();
+ }
+
+ int top = m_PaintStateStack.Count() - 1;
+
+ // More pops that pushes?
+ Assert( top >= 0 );
+
+ // Didn't pop in reverse order of push?
+ Assert( m_PaintStateStack[top].m_pPanel == pPanel );
+
+ m_PaintStateStack.Remove(top);
+
+ if (top > 0)
+ SetupPaintState( m_PaintStateStack[top-1] );
+
+// m_iBoundTexture = -1;
+}
+
+
+//-----------------------------------------------------------------------------
+// Color Setting methods
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetColor(int r, int g, int b, int a)
+{
+ Assert( g_bInDrawing );
+ m_DrawColor[0]=(unsigned char)r;
+ m_DrawColor[1]=(unsigned char)g;
+ m_DrawColor[2]=(unsigned char)b;
+ m_DrawColor[3]=(unsigned char)(a * m_flAlphaMultiplier);
+}
+
+void CMatSystemSurface::DrawSetColor(Color col)
+{
+ Assert( g_bInDrawing );
+ DrawSetColor(col[0], col[1], col[2], col[3]);
+}
+
+
+//-----------------------------------------------------------------------------
+// material Setting methods
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InternalSetMaterial( IMaterial *pMaterial )
+{
+ if (!pMaterial)
+ {
+ pMaterial = m_pWhite;
+ }
+
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ m_pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
+}
+
+
+//-----------------------------------------------------------------------------
+// Helper method to initialize vertices (transforms them into screen space too)
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InitVertex( vgui::Vertex_t &vertex, int x, int y, float u, float v )
+{
+ vertex.m_Position.Init( x + m_nTranslateX, y + m_nTranslateY );
+ vertex.m_TexCoord.Init( u, v );
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a line!
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawTexturedLineInternal( const Vertex_t &a, const Vertex_t &b )
+{
+ MAT_FUNC;
+
+ Assert( !m_bIn3DPaintMode );
+
+ // Don't bother drawing fully transparent lines
+ if( m_DrawColor[3] == 0 )
+ return;
+
+ vgui::Vertex_t verts[2] = { a, b };
+
+ verts[0].m_Position.x += m_nTranslateX + g_flPixelOffsetX;
+ verts[0].m_Position.y += m_nTranslateY + g_flPixelOffsetY;
+
+ verts[1].m_Position.x += m_nTranslateX + g_flPixelOffsetX;
+ verts[1].m_Position.y += m_nTranslateY + g_flPixelOffsetY;
+
+ vgui::Vertex_t clippedVerts[2];
+
+ if (!ClipLine( verts, clippedVerts ))
+ return;
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_LINES, 1 );
+
+ meshBuilder.Position3f( clippedVerts[0].m_Position.x, clippedVerts[0].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, clippedVerts[0].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( clippedVerts[1].m_Position.x, clippedVerts[1].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, clippedVerts[1].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+void CMatSystemSurface::DrawLine( int x0, int y0, int x1, int y1 )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Don't bother drawing fully transparent lines
+ if( m_DrawColor[3] == 0 )
+ return;
+
+ vgui::Vertex_t verts[2];
+ verts[0].Init( Vector2D( x0, y0 ), Vector2D( 0, 0 ) );
+ verts[1].Init( Vector2D( x1, y1 ), Vector2D( 1, 1 ) );
+
+ InternalSetMaterial( );
+ DrawTexturedLineInternal( verts[0], verts[1] );
+}
+
+
+void CMatSystemSurface::DrawTexturedLine( const Vertex_t &a, const Vertex_t &b )
+{
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+ DrawTexturedLineInternal( a, b );
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a line!
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawPolyLine( int *px, int *py ,int n )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ Assert( !m_bIn3DPaintMode );
+
+ // Don't bother drawing fully transparent lines
+ if( m_DrawColor[3] == 0 )
+ return;
+
+ InternalSetMaterial( );
+ meshBuilder.Begin( m_pMesh, MATERIAL_LINES, n );
+
+ for ( int i = 0; i < n ; i++ )
+ {
+ int inext = ( i + 1 ) % n;
+
+ vgui::Vertex_t verts[2];
+ vgui::Vertex_t clippedVerts[2];
+
+ int x0, y0, x1, y1;
+
+ x0 = px[ i ];
+ x1 = px[ inext ];
+ y0 = py[ i ];
+ y1 = py[ inext ];
+
+ InitVertex( verts[0], x0, y0, 0, 0 );
+ InitVertex( verts[1], x1, y1, 1, 1 );
+
+ if (!ClipLine( verts, clippedVerts ))
+ continue;
+
+ meshBuilder.Position3f( clippedVerts[0].m_Position.x+ g_flPixelOffsetX, clippedVerts[0].m_Position.y + g_flPixelOffsetY, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, clippedVerts[0].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( clippedVerts[1].m_Position.x+ g_flPixelOffsetX, clippedVerts[1].m_Position.y + g_flPixelOffsetY, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, clippedVerts[1].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+
+void CMatSystemSurface::DrawTexturedPolyLine( const vgui::Vertex_t *p,int n )
+{
+ MAT_FUNC;
+
+ int iPrev = n - 1;
+ for ( int i=0; i < n; i++ )
+ {
+ DrawTexturedLine( p[iPrev], p[i] );
+ iPrev = i;
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a quad:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawQuad( const vgui::Vertex_t &ul, const vgui::Vertex_t &lr, unsigned char *pColor )
+{
+ MAT_FUNC;
+
+ Assert( !m_bIn3DPaintMode );
+
+ if ( !m_pMesh )
+ return;
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
+
+ meshBuilder.Position3f( ul.m_Position.x, ul.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, ul.m_TexCoord.x, ul.m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( lr.m_Position.x, ul.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, lr.m_TexCoord.x, ul.m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( lr.m_Position.x, lr.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, lr.m_TexCoord.x, lr.m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( ul.m_Position.x, lr.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, ul.m_TexCoord.x, lr.m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws an array of quads
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawQuadArray( int quadCount, vgui::Vertex_t *pVerts, unsigned char *pColor, bool bShouldClip )
+{
+ MAT_FUNC;
+
+ Assert( !m_bIn3DPaintMode );
+
+ if ( !m_pMesh )
+ return;
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, quadCount );
+
+ vgui::Vertex_t ulc;
+ vgui::Vertex_t lrc;
+ vgui::Vertex_t *pulc;
+ vgui::Vertex_t *plrc;
+
+ if ( bShouldClip )
+ {
+ for ( int i = 0; i < quadCount; ++i )
+ {
+ PREFETCH360( &pVerts[ 2 * ( i + 1 ) ], 0 );
+
+ if ( !ClipRect( pVerts[2*i], pVerts[2*i + 1], &ulc, &lrc ) )
+ {
+ continue;
+ }
+ pulc = &ulc;
+ plrc = &lrc;
+
+ meshBuilder.Position3f( pulc->m_Position.x, pulc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, pulc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( plrc->m_Position.x, pulc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, pulc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( plrc->m_Position.x, plrc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, plrc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( pulc->m_Position.x, plrc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, plrc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+ }
+ else
+ {
+ for ( int i = 0; i < quadCount; ++i )
+ {
+ PREFETCH360( &pVerts[ 2 * ( i + 1 ) ], 0 );
+
+ pulc = &pVerts[2*i];
+ plrc = &pVerts[2*i + 1];
+
+ meshBuilder.Position3f( pulc->m_Position.x, pulc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, pulc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( plrc->m_Position.x, pulc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, pulc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( plrc->m_Position.x, plrc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, plrc->m_TexCoord.x, plrc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( pulc->m_Position.x, plrc->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( pColor );
+ meshBuilder.TexCoord2f( 0, pulc->m_TexCoord.x, plrc->m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws a rectangle colored with the current drawcolor
+// using the white material
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFilledRect( int x0, int y0, int x1, int y1 )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Don't even bother drawing fully transparent junk
+ if( m_DrawColor[3]!=0 )
+ {
+ vgui::Vertex_t rect[2];
+ vgui::Vertex_t clippedRect[2];
+ InitVertex( rect[0], x0, y0, 0, 0 );
+ InitVertex( rect[1], x1, y1, 0, 0 );
+
+ // Fully clipped?
+ if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
+ return;
+
+ InternalSetMaterial();
+ DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws an array of rectangles colored with the current drawcolor
+// using the white material
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFilledRectArray( IntRect *pRects, int numRects )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Don't even bother drawing fully transparent junk
+ if( m_DrawColor[3]==0 )
+ return;
+
+ if ( !m_pMesh )
+ return;
+
+ InternalSetMaterial( );
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, numRects );
+
+ for (int i = 0; i < numRects; ++i )
+ {
+ vgui::Vertex_t rect[2];
+ vgui::Vertex_t clippedRect[2];
+ InitVertex( rect[0], pRects[i].x0, pRects[i].y0, 0, 0 );
+ InitVertex( rect[1], pRects[i].x1, pRects[i].y1, 0, 0 );
+
+ ClipRect( rect[0], rect[1], &clippedRect[0], &clippedRect[1] );
+
+ vgui::Vertex_t &ul = clippedRect[0];
+ vgui::Vertex_t &lr = clippedRect[1];
+
+ meshBuilder.Position3f( ul.m_Position.x, ul.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
+
+ meshBuilder.Position3f( lr.m_Position.x, ul.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
+
+ meshBuilder.Position3f( lr.m_Position.x, lr.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
+
+ meshBuilder.Position3f( ul.m_Position.x, lr.m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 0>();
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+//-----------------------------------------------------------------------------
+// Draws a fade between the fadeStartPt and fadeEndPT with the current draw color oriented according to argument
+// Example: DrawFilledRectFastFade( 10, 10, 100, 20, 50, 60, 255, 128, true );
+// -this will draw
+// a solid rect (10,10,50,20) //alpha 255
+// a solid rect (50,10,60,20) //alpha faded from 255 to 128
+// a solid rect (60,10,100,20) //alpha 128
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFilledRectFastFade( int x0, int y0, int x1, int y1, int fadeStartPt, int fadeEndPt, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
+{
+ if( bHorizontal )
+ {
+ if( alpha0 )
+ {
+ DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha0 );
+ DrawFilledRect( x0, y0, fadeStartPt, y1 );
+ }
+ DrawFilledRectFade( fadeStartPt, y0, fadeEndPt, y1, alpha0, alpha1, true );
+ if( alpha1 )
+ {
+ DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha1 );
+ DrawFilledRect( fadeEndPt, y0, x1, y1 );
+ }
+ }
+ else
+ {
+ if( alpha0 )
+ {
+ DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha0 );
+ DrawFilledRect( x0, y0, x1, fadeStartPt );
+ }
+ DrawFilledRectFade( x0, fadeStartPt, x1, fadeEndPt, alpha0, alpha1, false );
+ if( alpha1 )
+ {
+ DrawSetColor( m_DrawColor[0], m_DrawColor[1], m_DrawColor[2], alpha1 );
+ DrawFilledRect( x0, fadeEndPt, x1, y1 );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Draws a fade with the current draw color oriented according to argument
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Scale the desired alphas by the surface alpha
+ float alphaScale = m_DrawColor[3] / 255.f;
+ alpha0 *= alphaScale;
+ alpha1 *= alphaScale;
+
+ // Don't even bother drawing fully transparent junk
+ if ( alpha0 == 0 && alpha1 == 0 )
+ return;
+
+ vgui::Vertex_t rect[2];
+ vgui::Vertex_t clippedRect[2];
+ InitVertex( rect[0], x0, y0, 0, 0 );
+ InitVertex( rect[1], x1, y1, 0, 0 );
+
+ // Fully clipped?
+ if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
+ return;
+
+ InternalSetMaterial();
+
+ unsigned char colors[4][4] = {{0}};
+ for ( int i=0; i<4; i++ )
+ {
+ // copy the rgb and leave the alpha at zero
+ Q_memcpy( colors[i], m_DrawColor, 3 );
+ }
+
+ unsigned char nAlpha0 = (alpha0 & 0xFF);
+ unsigned char nAlpha1 = (alpha1 & 0xFF);
+
+ if ( bHorizontal )
+ {
+ // horizontal fade
+ colors[0][3] = nAlpha0;
+ colors[1][3] = nAlpha1;
+ colors[2][3] = nAlpha1;
+ colors[3][3] = nAlpha0;
+ }
+ else
+ {
+ // vertical fade
+ colors[0][3] = nAlpha0;
+ colors[1][3] = nAlpha0;
+ colors[2][3] = nAlpha1;
+ colors[3][3] = nAlpha1;
+ }
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_QUADS, 1 );
+
+ meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( colors[0] );
+ meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[0].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( colors[1] );
+ meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[0].m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( clippedRect[1].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( colors[2] );
+ meshBuilder.TexCoord2f( 0, clippedRect[1].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( clippedRect[0].m_Position.x, clippedRect[1].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( colors[3] );
+ meshBuilder.TexCoord2f( 0, clippedRect[0].m_TexCoord.x, clippedRect[1].m_TexCoord.y );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws an unfilled rectangle in the current drawcolor
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawOutlinedRect(int x0,int y0,int x1,int y1)
+{
+ MAT_FUNC;
+
+ // Don't even bother drawing fully transparent junk
+ if ( m_DrawColor[3] == 0 )
+ return;
+
+ DrawFilledRect(x0,y0,x1,y0+1); //top
+ DrawFilledRect(x0,y1-1,x1,y1); //bottom
+ DrawFilledRect(x0,y0+1,x0+1,y1-1); //left
+ DrawFilledRect(x1-1,y0+1,x1,y1-1); //right
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws an outlined circle in the current drawcolor
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawOutlinedCircle(int x, int y, int radius, int segments)
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ Assert( !m_bIn3DPaintMode );
+
+ // Don't even bother drawing fully transparent junk
+ if( m_DrawColor[3]==0 )
+ return;
+
+ // NOTE: Gotta use lines instead of linelist or lineloop due to clipping
+ InternalSetMaterial( );
+ meshBuilder.Begin( m_pMesh, MATERIAL_LINES, segments );
+
+ vgui::Vertex_t renderVertex[2];
+ vgui::Vertex_t vertex[2];
+ vertex[0].m_Position.Init( m_nTranslateX + x + radius, m_nTranslateY + y );
+ vertex[0].m_TexCoord.Init( 1.0f, 0.5f );
+
+ float invDelta = 2.0f * M_PI / segments;
+ for ( int i = 1; i <= segments; ++i )
+ {
+ float flRadians = i * invDelta;
+ float ca = cos( flRadians );
+ float sa = sin( flRadians );
+
+ // Rotate it around the circle
+ vertex[1].m_Position.x = m_nTranslateX + x + (radius * ca);
+ vertex[1].m_Position.y = m_nTranslateY + y + (radius * sa);
+ vertex[1].m_TexCoord.x = 0.5f * (ca + 1.0f);
+ vertex[1].m_TexCoord.y = 0.5f * (sa + 1.0f);
+
+ if (ClipLine( vertex, renderVertex ))
+ {
+ meshBuilder.Position3f( renderVertex[0].m_Position.x, renderVertex[0].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, renderVertex[0].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+
+ meshBuilder.Position3f( renderVertex[1].m_Position.x, renderVertex[1].m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, renderVertex[1].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+
+ vertex[0].m_Position = vertex[1].m_Position;
+ vertex[0].m_TexCoord = vertex[1].m_TexCoord;
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+}
+
+
+//-----------------------------------------------------------------------------
+// Loads a particular texture (material)
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::CreateNewTextureID( bool procedural /*=false*/ )
+{
+ return TextureDictionary()->CreateTexture( procedural );
+}
+
+void CMatSystemSurface::DestroyTextureID( int id )
+{
+ TextureDictionary()->DestroyTexture( id );
+}
+
+bool CMatSystemSurface::DeleteTextureByID(int id)
+{
+ TextureDictionary()->DestroyTexture( id );
+ return false;
+}
+
+#ifdef _X360
+void CMatSystemSurface::UncacheUnusedMaterials()
+{
+ // unbind any currently set texture (which may be uncached)
+ DrawSetTexture( -1 );
+
+ // X360TBD: Need to only destroy "marked" textures
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : id -
+// *filename -
+// maxlen -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::DrawGetTextureFile(int id, char *filename, int maxlen )
+{
+ if ( !TextureDictionary()->IsValidId( id ) )
+ return false;
+
+ IMaterial *texture = TextureDictionary()->GetTextureMaterial(id);
+ if ( !texture )
+ return false;
+
+ Q_strncpy( filename, texture->GetName(), maxlen );
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : id - texture id
+// Output : returns IMaterial for the referenced texture
+//-----------------------------------------------------------------------------
+IVguiMatInfo *CMatSystemSurface::DrawGetTextureMatInfoFactory(int id)
+{
+ if ( !TextureDictionary()->IsValidId( id ) )
+ return NULL;
+
+ IMaterial *texture = TextureDictionary()->GetTextureMaterial(id);
+
+ if ( texture == NULL )
+ return NULL;
+
+ return new CVguiMatInfo(texture);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *filename -
+// Output : int
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::DrawGetTextureId( char const *filename )
+{
+ return TextureDictionary()->FindTextureIdForTextureFile( filename );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pTexture
+// Output : int
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::DrawGetTextureId( ITexture *pTexture )
+{
+ return TextureDictionary()->CreateTextureByTexture( pTexture );
+}
+
+
+//-----------------------------------------------------------------------------
+// Associates a texture with a material file (also binds it)
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextureFile(int id, const char *pFileName, int hardwareFilter, bool forceReload /*= false*/)
+{
+ TextureDictionary()->BindTextureToFile( id, pFileName );
+ DrawSetTexture( id );
+}
+
+
+//-----------------------------------------------------------------------------
+// Associates a texture with a material file (also binds it)
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextureMaterial(int id, IMaterial *pMaterial)
+{
+ TextureDictionary()->BindTextureToMaterial( id, pMaterial );
+ DrawSetTexture( id );
+}
+
+IMaterial *CMatSystemSurface::DrawGetTextureMaterial( int id )
+{
+ return TextureDictionary()->GetTextureMaterial( id );
+}
+
+
+void CMatSystemSurface::ReferenceProceduralMaterial( int id, int referenceId, IMaterial *pMaterial )
+{
+ TextureDictionary()->BindTextureToMaterialReference( id, referenceId, pMaterial );
+}
+
+
+//-----------------------------------------------------------------------------
+// Binds a texture
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTexture( int id )
+{
+ // if we're switching textures, flush any batched text
+ if ( id != m_iBoundTexture )
+ {
+ DrawFlushText();
+ m_iBoundTexture = id;
+
+ if ( IsX360() && id == -1 )
+ {
+ // ensure we unbind current material that may go away
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ pRenderContext->Bind( m_pWhite );
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns texture size
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawGetTextureSize(int id, int &iWide, int &iTall)
+{
+ TextureDictionary()->GetTextureSize( id, iWide, iTall );
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a textured rectangle
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawTexturedRect( int x0, int y0, int x1, int y1 )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Don't even bother drawing fully transparent junk
+ if( m_DrawColor[3] == 0 )
+ return;
+
+ float s0, t0, s1, t1;
+ TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
+
+ vgui::Vertex_t rect[2];
+ vgui::Vertex_t clippedRect[2];
+ InitVertex( rect[0], x0, y0, s0, t0 );
+ InitVertex( rect[1], x1, y1, s1, t1 );
+
+ // Fully clipped?
+ if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
+ return;
+
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+ DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
+}
+
+//-----------------------------------------------------------------------------
+// Draws a textured rectangle
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // Don't even bother drawing fully transparent junk
+ if( m_DrawColor[3] == 0 )
+ return;
+
+ float s0, t0, s1, t1;
+ TextureDictionary()->GetTextureTexCoords( m_iBoundTexture, s0, t0, s1, t1 );
+
+ float ssize = s1 - s0;
+ float tsize = t1 - t0;
+
+ // Rescale tex values into range of s0 to s1 ,etc.
+ texs0 = s0 + texs0 * ( ssize );
+ texs1 = s0 + texs1 * ( ssize );
+ text0 = t0 + text0 * ( tsize );
+ text1 = t0 + text1 * ( tsize );
+
+ vgui::Vertex_t rect[2];
+ vgui::Vertex_t clippedRect[2];
+ InitVertex( rect[0], x0, y0, texs0, text0 );
+ InitVertex( rect[1], x1, y1, texs1, text1 );
+
+ // Fully clipped?
+ if ( !ClipRect(rect[0], rect[1], &clippedRect[0], &clippedRect[1]) )
+ return;
+
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+ DrawQuad( clippedRect[0], clippedRect[1], m_DrawColor );
+}
+
+//-----------------------------------------------------------------------------
+// Draws a textured polygon
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawTexturedPolygon(int n, Vertex_t *pVertices, bool bClipVertices /*= true*/ )
+{
+ MAT_FUNC;
+
+ Assert( !m_bIn3DPaintMode );
+
+ Assert( g_bInDrawing );
+
+ // Don't even bother drawing fully transparent junk
+ if( (n == 0) || (m_DrawColor[3]==0) )
+ return;
+
+ if ( bClipVertices )
+ {
+ int iCount;
+ Vertex_t **ppClippedVerts = NULL;
+ iCount = ClipPolygon( n, pVertices, m_nTranslateX, m_nTranslateY, &ppClippedVerts );
+ if (iCount <= 0)
+ return;
+
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_POLYGON, iCount );
+
+ for (int i = 0; i < iCount; ++i)
+ {
+ meshBuilder.Position3f( ppClippedVerts[i]->m_Position.x, ppClippedVerts[i]->m_Position.y, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, ppClippedVerts[i]->m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+ }
+ else
+ {
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+
+ meshBuilder.Begin( m_pMesh, MATERIAL_POLYGON, n );
+
+ for (int i = 0; i < n; ++i)
+ {
+ meshBuilder.Position3f( pVertices[i].m_Position.x + m_nTranslateX, pVertices[i].m_Position.y + m_nTranslateY, m_flZPos );
+ meshBuilder.Color4ubv( m_DrawColor );
+ meshBuilder.TexCoord2fv( 0, pVertices[i].m_TexCoord.Base() );
+ meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
+ }
+
+ meshBuilder.End();
+ m_pMesh->Draw();
+ }
+}
+
+
+
+//-----------------------------------------------------------------------------
+//
+// Font-related methods begin here
+//
+//-----------------------------------------------------------------------------
+
+
+//-----------------------------------------------------------------------------
+// Purpose: creates a new empty font
+//-----------------------------------------------------------------------------
+HFont CMatSystemSurface::CreateFont()
+{
+ MAT_FUNC;
+
+ return FontManager().CreateFont();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds glyphs to a font created by CreateFont()
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::SetFontGlyphSet(HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin, int nRangeMax)
+{
+ return FontManager().SetFontGlyphSet(font, windowsFontName, tall, weight, blur, scanlines, flags, nRangeMin, nRangeMax);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds glyphs to a font created by CreateFont()
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::SetBitmapFontGlyphSet(HFont font, const char *windowsFontName, float scalex, float scaley, int flags)
+{
+ return FontManager().SetBitmapFontGlyphSet(font, windowsFontName, scalex, scaley, flags);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the max height of a font
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetFontTall(HFont font)
+{
+ return FontManager().GetFontTall(font);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the requested height of a font
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetFontTallRequested(HFont font)
+{
+ return FontManager().GetFontTallRequested(font);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the max height of a font
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetFontAscent(HFont font, wchar_t wch)
+{
+ return FontManager().GetFontAscent(font,wch);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : font -
+// Output : Returns true on success, false on failure.
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::IsFontAdditive(HFont font)
+{
+ return FontManager().IsFontAdditive(font);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the abc widths of a single character
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetCharABCwide(HFont font, int ch, int &a, int &b, int &c)
+{
+ FontManager().GetCharABCwide(font, ch, a, b, c);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the pixel width of a single character
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetCharacterWidth(HFont font, int ch)
+{
+ return FontManager().GetCharacterWidth(font, ch);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the kerned width of this char
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetKernedCharWidth( HFont font, wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &abcA ) //, float &abcC )
+{
+ float abcC = 0.0f;
+ FontManager().GetKernedCharWidth(font, ch, chBefore, chAfter, wide, abcA, abcC );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the area of a text string, including newlines
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall)
+{
+ FontManager().GetTextSize(font, text, wide, tall);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: adds a custom font file (only supports true type font files (.ttf) for now)
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::AddCustomFontFile( const char *fontName, const char *fontFileName )
+{
+ if ( IsX360() )
+ {
+ // custom fonts are not supported (not needed) on xbox, all .vfonts are offline converted to ttfs
+ // ttfs are mounted/handled elsewhere
+ return true;
+ }
+ MAT_FUNC;
+
+ char fullPath[MAX_PATH];
+ bool bFound = false;
+ // windows needs an absolute path for ttf
+ bFound = g_pFullFileSystem->GetLocalPath( fontFileName, fullPath, sizeof( fullPath ) );
+ if ( !bFound )
+ {
+ Warning( "Couldn't find custom font file '%s'\n", fontFileName );
+ return false;
+ }
+
+ // only add if it's not already in the list
+ Q_strlower( fullPath );
+ CUtlSymbol sym(fullPath);
+ int i;
+ for ( i = 0; i < m_CustomFontFileNames.Count(); i++ )
+ {
+ if ( m_CustomFontFileNames[i] == sym )
+ break;
+ }
+ if ( !m_CustomFontFileNames.IsValidIndex( i ) )
+ {
+ m_CustomFontFileNames.AddToTail( fullPath );
+
+ if ( IsPC() )
+ {
+ // make sure it's on disk
+ // only do this once for each font since in steam it will overwrite the
+ // registered font file, causing windows to invalidate the font
+ g_pFullFileSystem->GetLocalCopy( fullPath );
+ }
+ }
+
+ // try and use the optimal custom font loader, will makes sure fonts are unloaded properly
+ // this function is in a newer version of the gdi library (win2k+), so need to try get it directly
+#if defined( WIN32 ) && !defined( _X360 )
+ bool successfullyAdded = false;
+ HMODULE gdiModule = ::LoadLibrary("gdi32.dll");
+ if (gdiModule)
+ {
+ typedef int (WINAPI *AddFontResourceExProc)(LPCTSTR, DWORD, PVOID);
+ AddFontResourceExProc pAddFontResourceEx = (AddFontResourceExProc)::GetProcAddress(gdiModule, "AddFontResourceExA");
+ if (pAddFontResourceEx)
+ {
+ int result = (*pAddFontResourceEx)(fullPath, 0x10, NULL);
+ if (result > 0)
+ {
+ successfullyAdded = true;
+ }
+ }
+ ::FreeLibrary(gdiModule);
+ }
+
+ // add to windows
+ bool success = successfullyAdded || (::AddFontResource(fullPath) > 0);
+ if ( !success )
+ {
+ Msg( "Failed to load custom font file '%s'\n", fullPath );
+ }
+ Assert( success );
+ return success;
+#elif OSX
+
+ FSRef ref;
+ OSStatus err = FSPathMakeRef( (const UInt8*)fullPath, &ref, NULL );
+ if ( err == noErr )
+ err = ATSFontActivateFromFileReference( &ref, kATSFontContextLocal, kATSFontFormatUnspecified, NULL, kATSOptionFlagsDefault, NULL );
+
+ return err == noErr;
+
+#elif LINUX
+
+ int size;
+ if ( CMatSystemSurface::FontDataHelper( fontName, size, fontFileName ) )
+ return true;
+ return false;
+
+#elif defined( _X360 )
+#include "xbox/xbox_win32stubs.h"
+#else
+#error
+#endif
+}
+
+#ifdef LINUX
+
+static void RemoveSpaces( CUtlString &str )
+{
+ char *dst = str.GetForModify();
+
+ for( int i = 0; i < str.Length(); i++ )
+ {
+ if( ( str[ i ] != ' ' ) && ( str[ i ] != '-' ) )
+ {
+ *dst++ = str[ i ];
+ }
+ }
+
+ *dst = 0;
+}
+
+void *CMatSystemSurface::FontDataHelper( const char *pchFontName, int &size, const char *fontFileName )
+{
+ size = 0;
+
+ if( fontFileName )
+ {
+ // If we were given a fontFileName, then load that bugger and shove it in the cache.
+
+ // Just load the font data, decrypt in memory and register for this process
+ CUtlBuffer buf;
+ if ( !g_pFullFileSystem->ReadFile( fontFileName, NULL, buf ) )
+ {
+ Msg( "Failed to load custom font file '%s'\n", fontFileName );
+ return NULL;
+ }
+
+ FT_Face face;
+ const FT_Error error = FT_New_Memory_Face( FontManager().GetFontLibraryHandle(), (FT_Byte *)buf.Base(), buf.TellPut(), 0, &face );
+
+ if ( error )
+ {
+ // FT_Err_Unknown_File_Format, etc.
+ Msg( "ERROR %d: UNABLE TO LOAD FONT FILE %s\n", error, fontFileName );
+ return NULL;
+ }
+
+ if( !pchFontName )
+ {
+ // If we weren't passed a font name for this thing, then use the one from the face.
+ pchFontName = face->family_name;
+ if ( !pchFontName || !pchFontName[ 0 ] )
+ {
+ pchFontName = FT_Get_Postscript_Name( face );
+ }
+ }
+
+ // Replace spaces and dashes with underscores.
+ CUtlString strFontName( pchFontName );
+ RemoveSpaces( strFontName );
+
+ font_entry entry;
+ entry.size = buf.TellPut();
+ entry.data = malloc( entry.size );
+ memcpy( entry.data, buf.Base(), entry.size );
+ m_FontData.Insert( strFontName.Get(), entry );
+
+ FT_Done_Face( face );
+
+ size = entry.size;
+ return entry.data;
+ }
+ else
+ {
+ // Replace spaces and dashes with underscores.
+ CUtlString strFontName( pchFontName );
+ RemoveSpaces( strFontName );
+
+ int iIndex = m_FontData.Find( strFontName.Get() );
+ if ( iIndex != m_FontData.InvalidIndex() )
+ {
+ size = m_FontData[ iIndex ].size;
+ return m_FontData[ iIndex ].data;
+ }
+ }
+
+ return NULL;
+}
+
+#endif // LINUX
+
+//-----------------------------------------------------------------------------
+// Purpose: adds a bitmap font file
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::AddBitmapFontFile( const char *fontFileName )
+{
+ MAT_FUNC;
+
+ bool bFound = false;
+ bFound = ( ( g_pFullFileSystem->GetDVDMode() == DVDMODE_STRICT ) || g_pFullFileSystem->FileExists( fontFileName, IsX360() ? "GAME" : NULL ) );
+ if ( !bFound )
+ {
+ Msg( "Couldn't find bitmap font file '%s'\n", fontFileName );
+ return false;
+ }
+ char path[MAX_PATH];
+ Q_strncpy( path, fontFileName, MAX_PATH );
+
+ // only add if it's not already in the list
+ Q_strlower( path );
+ CUtlSymbol sym( path );
+ int i;
+ for ( i = 0; i < m_BitmapFontFileNames.Count(); i++ )
+ {
+ if ( m_BitmapFontFileNames[i] == sym )
+ break;
+ }
+ if ( !m_BitmapFontFileNames.IsValidIndex( i ) )
+ {
+ m_BitmapFontFileNames.AddToTail( path );
+
+ if ( IsPC() )
+ {
+ // make sure it's on disk
+ // only do this once for each font since in steam it will overwrite the
+ // registered font file, causing windows to invalidate the font
+ g_pFullFileSystem->GetLocalCopy( path );
+ }
+ }
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetBitmapFontName( const char *pName, const char *pFontFilename )
+{
+ char fontPath[MAX_PATH];
+ Q_strncpy( fontPath, pFontFilename, MAX_PATH );
+ Q_strlower( fontPath );
+
+ CUtlSymbol sym( fontPath );
+ int i;
+ for (i = 0; i < m_BitmapFontFileNames.Count(); i++)
+ {
+ if ( m_BitmapFontFileNames[i] == sym )
+ {
+ // found it, update the mapping
+ int index = m_BitmapFontFileMapping.Find( pName );
+ if ( !m_BitmapFontFileMapping.IsValidIndex( index ) )
+ {
+ index = m_BitmapFontFileMapping.Insert( pName );
+ }
+ m_BitmapFontFileMapping.Element( index ) = i;
+ break;
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+const char *CMatSystemSurface::GetBitmapFontName( const char *pName )
+{
+ // find it in the mapping symbol table
+ int index = m_BitmapFontFileMapping.Find( pName );
+ if ( index == m_BitmapFontFileMapping.InvalidIndex() )
+ {
+ return "";
+ }
+
+ return m_BitmapFontFileNames[m_BitmapFontFileMapping.Element( index )].String();
+}
+
+void CMatSystemSurface::ClearTemporaryFontCache( void )
+{
+ FontManager().ClearTemporaryFontCache();
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Force a set of characters to be rendered into the font page.
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PrecacheFontCharacters( HFont font, const wchar_t *pCharacterString )
+{
+ wchar_t *pCommonChars = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.!:-/%";
+ MAT_FUNC;
+
+ if ( !pCharacterString || !pCharacterString[0] )
+ {
+ // use the common chars, alternate languages are not handled
+ pCharacterString = pCommonChars;
+ }
+
+ StartDrawing();
+ DrawSetTextFont( font );
+
+ int numChars = 0;
+ while( pCharacterString[ numChars ] )
+ {
+ numChars++;
+ }
+ int *pTextureIDs_ignored = (int *)_alloca( numChars*sizeof( int ) );
+ float **pTexCoords_ignored = (float **)_alloca( numChars*sizeof( float * ) );
+ g_FontTextureCache.GetTextureForChars( m_hCurrentFont, FONT_DRAW_DEFAULT, pCharacterString, pTextureIDs_ignored, pTexCoords_ignored, numChars );
+
+ FinishDrawing();
+}
+
+const char *CMatSystemSurface::GetFontName( HFont font )
+{
+ return FontManager().GetFontName( font );
+}
+
+const char *CMatSystemSurface::GetFontFamilyName( HFont font )
+{
+ return FontManager().GetFontFamilyName( font );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextFont(HFont font)
+{
+ Assert( g_bInDrawing );
+
+ m_hCurrentFont = font;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders any batched up text
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFlushText()
+{
+ if ( !m_nBatchedCharVertCount )
+ return;
+
+ {
+ // don't log entry unless actual work happens..
+ MAT_FUNC;
+
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(m_iBoundTexture);
+ InternalSetMaterial( pMaterial );
+ DrawQuadArray( m_nBatchedCharVertCount / 2, m_BatchedCharVerts, m_DrawTextColor );
+ m_nBatchedCharVertCount = 0;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Sets the text color
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextColor(int r, int g, int b, int a)
+{
+ int adjustedAlpha = (a * m_flAlphaMultiplier);
+
+ if ( r != m_DrawTextColor[0] || g != m_DrawTextColor[1] || b != m_DrawTextColor[2] || adjustedAlpha != m_DrawTextColor[3] )
+ {
+ // text color changed, flush any existing text
+ DrawFlushText();
+
+ m_DrawTextColor[0] = (unsigned char)r;
+ m_DrawTextColor[1] = (unsigned char)g;
+ m_DrawTextColor[2] = (unsigned char)b;
+ m_DrawTextColor[3] = (unsigned char)adjustedAlpha;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: alternate color set
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextColor(Color col)
+{
+ DrawSetTextColor(col[0], col[1], col[2], col[3]);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: change the scale of a bitmap font
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextScale(float sx, float sy)
+{
+ FontManager().SetFontScale( m_hCurrentFont, sx, sy );
+}
+
+//-----------------------------------------------------------------------------
+// Text rendering location
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetTextPos(int x, int y)
+{
+ Assert( g_bInDrawing );
+
+ m_pDrawTextPos[0] = x;
+ m_pDrawTextPos[1] = y;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawGetTextPos(int& x,int& y)
+{
+ Assert( g_bInDrawing );
+
+ x = m_pDrawTextPos[0];
+ y = m_pDrawTextPos[1];
+}
+
+#pragma warning( disable : 4706 )
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawUnicodeString( const wchar_t *pString, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
+{
+ // skip fully transparent characters
+ if ( m_DrawTextColor[3] == 0 )
+ return;
+
+ //hushed MAT_FUNC;
+#ifdef POSIX
+ DrawPrintText( pString, V_wcslen( pString ) , drawType );
+#else
+ wchar_t ch;
+
+ while ( ( ch = *pString++ ) )
+ {
+ DrawUnicodeChar( ch );
+ }
+#endif
+}
+#pragma warning( default : 4706 )
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawUnicodeChar(wchar_t ch, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
+{
+ // skip fully transparent characters
+ if ( m_DrawTextColor[3] == 0 )
+ return;
+ //hushed MAT_FUNC;
+
+ CharRenderInfo info;
+ info.drawType = drawType;
+ if ( DrawGetUnicodeCharRenderInfo( ch, info ) )
+ {
+ DrawRenderCharFromInfo( info );
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::DrawGetUnicodeCharRenderInfo( wchar_t ch, CharRenderInfo& info )
+{
+ //hushed MAT_FUNC;
+
+ Assert( g_bInDrawing );
+ info.valid = false;
+
+ if ( !m_hCurrentFont )
+ {
+ return info.valid;
+ }
+
+ PREFETCH360( &m_BatchedCharVerts[ m_nBatchedCharVertCount ], 0 );
+
+ info.valid = true;
+ info.ch = ch;
+ DrawGetTextPos(info.x, info.y);
+
+ info.currentFont = m_hCurrentFont;
+ info.fontTall = GetFontTall(m_hCurrentFont);
+
+ GetCharABCwide(m_hCurrentFont, ch, info.abcA, info.abcB, info.abcC);
+ bool bUnderlined = FontManager().GetFontUnderlined( m_hCurrentFont );
+
+ // Do prestep before generating texture coordinates, etc.
+ if ( !bUnderlined )
+ {
+ info.x += info.abcA;
+ }
+
+ // get the character texture from the cache
+ info.textureId = 0;
+ float *texCoords = NULL;
+ if (!g_FontTextureCache.GetTextureForChar(m_hCurrentFont, info.drawType, ch, &info.textureId, &texCoords))
+ {
+ info.valid = false;
+ return info.valid;
+ }
+
+ int fontWide = info.abcB;
+ if ( bUnderlined )
+ {
+ fontWide += ( info.abcA + info.abcC );
+ info.x-= info.abcA;
+ }
+
+ // Because CharRenderInfo has a pointer to the verts, we need to keep m_BatchedCharVerts in sync, so if we
+ // will be flushing the text when we get to this char, flush it now instead.
+ if ( info.textureId != m_iBoundTexture )
+ {
+ DrawFlushText();
+ }
+
+ // This avoid copying the data in the nonclipped case!!! (X360)
+ info.verts = &m_BatchedCharVerts[ m_nBatchedCharVertCount ];
+ InitVertex( info.verts[0], info.x, info.y, texCoords[0], texCoords[1] );
+ InitVertex( info.verts[1], info.x + fontWide, info.y + info.fontTall, texCoords[2], texCoords[3] );
+
+ info.shouldclip = true;
+
+ return info.valid;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: batches up characters for rendering
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawRenderCharInternal( const CharRenderInfo& info )
+{
+ //hushed MAT_FUNC;
+
+ Assert( g_bInDrawing );
+
+ // xbox opts out of pricey/pointless text clipping
+ if ( IsPC() && info.shouldclip )
+ {
+ Vertex_t clip[ 2 ];
+ clip[ 0 ] = info.verts[ 0 ];
+ clip[ 1 ] = info.verts[ 1 ];
+ if ( !ClipRect( clip[0], clip[1], &info.verts[0], &info.verts[1] ) )
+ {
+ // Fully clipped
+ return;
+ }
+ }
+
+ m_nBatchedCharVertCount += 2;
+
+ if ( m_nBatchedCharVertCount >= MAX_BATCHED_CHAR_VERTS - 2 )
+ {
+ DrawFlushText();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawRenderCharFromInfo( const CharRenderInfo& info )
+{
+ //hushed MAT_FUNC;
+
+ if ( !info.valid )
+ return;
+
+ int x = info.x;
+
+ // get the character texture from the cache
+ DrawSetTexture( info.textureId );
+
+ DrawRenderCharInternal( info );
+
+ // Only do post step
+ x += ( info.abcB + info.abcC );
+
+ // Update cursor pos
+ DrawSetTextPos(x, info.y);
+}
+
+//-----------------------------------------------------------------------------
+// Renders a text buffer
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawPrintText(const wchar_t *text, int iTextLen, FontDrawType_t drawType /*= FONT_DRAW_DEFAULT */ )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+ if (!text)
+ return;
+
+ if (!m_hCurrentFont)
+ return;
+
+ int x = m_pDrawTextPos[0] + m_nTranslateX;
+ int y = m_pDrawTextPos[1] + m_nTranslateY;
+
+ int iTall = GetFontTall(m_hCurrentFont);
+ int iLastTexId = -1;
+
+ int iCount = 0;
+ vgui::Vertex_t *pQuads = (vgui::Vertex_t*)stackalloc((2 * iTextLen) * sizeof(vgui::Vertex_t) );
+ bool bUnderlined = FontManager().GetFontUnderlined( m_hCurrentFont );
+
+ int iTotalWidth = 0;
+ for (int i=0; i<iTextLen; ++i)
+ {
+ wchar_t ch = text[i];
+
+#if USE_GETKERNEDCHARWIDTH
+ //iTotalWidth += abcA;
+ float flWide;
+ float flabcA;
+ float flabcC;
+ wchar_t chBefore = 0;
+ wchar_t chAfter = 0;
+ if ( i > 0 )
+ chBefore = text[i-1];
+ if ( i < (iTextLen-1) )
+ chAfter = text[i+1];
+ FontManager().GetKernedCharWidth( m_hCurrentFont, ch, chBefore, chAfter, flWide, flabcA, flabcC );
+
+ int abcA,abcB,abcC;
+ // also grab the single char dimensions so we match the texture size to the one in the font page,
+ // different to the amount we step ahead once rendered
+ GetCharABCwide(m_hCurrentFont, ch, abcA, abcB, abcC);
+
+ int textureWide = abcB;
+ if ( bUnderlined )
+ {
+ textureWide += ( abcA + abcC );
+ x-= flabcA;
+ }
+#else
+ int abcA,abcB,abcC;
+ GetCharABCwide(m_hCurrentFont, ch, abcA, abcB, abcC);
+ int textureWide = abcB;
+ if ( bUnderlined )
+ {
+ textureWide += ( abcA + abcC );
+ x-= abcA;
+ }
+ float flabcA = abcA;
+ float flWide = abcA + abcB + abcC;
+#endif
+
+ if ( !iswspace( ch ) || bUnderlined )
+ {
+ // get the character texture from the cache
+ int iTexId = 0;
+ float *texCoords = NULL;
+ if (!g_FontTextureCache.GetTextureForChar(m_hCurrentFont, drawType, ch, &iTexId, &texCoords))
+ continue;
+
+ Assert( texCoords );
+
+ if (iTexId != iLastTexId)
+ {
+ // FIXME: At the moment, we just draw all the batched up
+ // text when the font changes. We Should batch up per material
+ // and *then* draw
+ if (iCount)
+ {
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(iLastTexId);
+ InternalSetMaterial( pMaterial );
+ DrawQuadArray( iCount, pQuads, m_DrawTextColor, IsPC() );
+ iCount = 0;
+ }
+
+ iLastTexId = iTexId;
+ }
+
+ vgui::Vertex_t &ul = pQuads[2*iCount];
+ vgui::Vertex_t &lr = pQuads[2*iCount + 1];
+ ++iCount;
+
+ ul.m_Position.x = x + iTotalWidth + floor(flabcA + 0.6);
+ ul.m_Position.y = y;
+ lr.m_Position.x = ul.m_Position.x + textureWide;
+ lr.m_Position.y = ul.m_Position.y + iTall;
+
+ // Gets at the texture coords for this character in its texture page
+ /*
+ float tex_U0_bias = prc->Knob("tex-U0-bias");
+ float tex_V0_bias = prc->Knob("tex-V0-bias");
+ float tex_U1_bias = prc->Knob("tex-U1-bias");
+ float tex_V1_bias = prc->Knob("tex-V1-bias");
+
+ ul.m_TexCoord[0] = texCoords[0] + tex_U0_bias;
+ ul.m_TexCoord[1] = texCoords[1] + tex_V0_bias;
+ lr.m_TexCoord[0] = texCoords[2] + tex_U1_bias;
+ lr.m_TexCoord[1] = texCoords[3] + tex_V1_bias;
+ */
+
+ ul.m_TexCoord[0] = texCoords[0];
+ ul.m_TexCoord[1] = texCoords[1];
+ lr.m_TexCoord[0] = texCoords[2];
+ lr.m_TexCoord[1] = texCoords[3];
+ }
+
+ iTotalWidth += floor(flWide+0.6);
+ }
+
+ // Draw any left-over characters
+ if (iCount)
+ {
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial(iLastTexId);
+ InternalSetMaterial( pMaterial );
+ DrawQuadArray( iCount, pQuads, m_DrawTextColor, IsPC() );
+ }
+
+ m_pDrawTextPos[0] += iTotalWidth;
+
+ stackfree(pQuads);
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the screen size
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetScreenSize(int &iWide, int &iTall)
+{
+ if ( m_ScreenSizeOverride.m_bActive )
+ {
+ iWide = m_ScreenSizeOverride.m_nValue[ 0 ];
+ iTall = m_ScreenSizeOverride.m_nValue[ 1 ];
+ return;
+ }
+
+ int x, y;
+
+ // mikesart: This is just sticking in unnecessary BeginRender/EndRender calls to the queue.
+ // CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ IMatRenderContext *pRenderContext = g_pMaterialSystem->GetRenderContext();
+ pRenderContext->GetViewport( x, y, iWide, iTall );
+}
+
+bool CMatSystemSurface::ForceScreenSizeOverride( bool bState, int wide, int tall )
+{
+ bool bWasSet = m_ScreenSizeOverride.m_bActive;
+ m_ScreenSizeOverride.m_bActive = bState;
+ m_ScreenSizeOverride.m_nValue[ 0 ] = wide;
+ m_ScreenSizeOverride.m_nValue[ 1 ] = tall;
+ return bWasSet;
+}
+
+// LocalToScreen, ParentLocalToScreen fixups for explicit PaintTraverse calls on Panels not at 0, 0 position
+bool CMatSystemSurface::ForceScreenPosOffset( bool bState, int x, int y )
+{
+ bool bWasSet = m_ScreenPosOverride.m_bActive;
+ m_ScreenPosOverride.m_bActive = bState;
+ m_ScreenPosOverride.m_nValue[ 0 ] = x;
+ m_ScreenPosOverride.m_nValue[ 1 ] = y;
+ return bWasSet;
+}
+
+void CMatSystemSurface::OffsetAbsPos( int &x, int &y )
+{
+ if ( !m_ScreenPosOverride.m_bActive )
+ return;
+
+ x += m_ScreenPosOverride.m_nValue[ 0 ];
+ y += m_ScreenPosOverride.m_nValue[ 1 ];
+}
+
+
+bool CMatSystemSurface::IsScreenSizeOverrideActive( void )
+{
+ return ( m_ScreenSizeOverride.m_bActive );
+}
+
+bool CMatSystemSurface::IsScreenPosOverrideActive( void )
+{
+ return ( m_ScreenPosOverride.m_bActive );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Notification of a new screen size
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::OnScreenSizeChanged( int nOldWidth, int nOldHeight )
+{
+ int iNewWidth, iNewHeight;
+ GetScreenSize( iNewWidth, iNewHeight );
+
+ Msg( "Changing resolutions from (%d, %d) -> (%d, %d)\n", nOldWidth, nOldHeight, iNewWidth, iNewHeight );
+
+ // update the root panel size
+ ipanel()->SetSize(m_pEmbeddedPanel, iNewWidth, iNewHeight);
+
+ // notify every panel
+ VPANEL panel = GetEmbeddedPanel();
+ ivgui()->PostMessage(panel, new KeyValues("OnScreenSizeChanged", "oldwide", nOldWidth, "oldtall", nOldHeight), NULL);
+
+ // Run a frame of the GUI to notify all subwindows of the message size change
+ ivgui()->RunFrame();
+
+ // clear font texture cache
+ ResetFontCaches();
+}
+
+// Causes fonts to get reloaded, etc.
+void CMatSystemSurface::ResetFontCaches()
+{
+ // Don't do this on x360!!!
+ if ( IsX360() )
+ return;
+
+ // clear font texture cache
+ g_FontTextureCache.Clear();
+ m_iBoundTexture = -1;
+
+ // reload fonts
+ FontManager().ClearAllFonts();
+ scheme()->ReloadFonts();
+
+ // Run a frame of the GUI to notify all subwindows of the message size change
+ ivgui()->RunFrame();
+}
+
+//-----------------------------------------------------------------------------
+// Returns the size of the embedded panel
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetWorkspaceBounds(int &x, int &y, int &iWide, int &iTall)
+{
+ if ( m_ScreenSizeOverride.m_bActive )
+ {
+ x = y = 0;
+ iWide = m_ScreenSizeOverride.m_nValue[ 0 ];
+ iTall = m_ScreenSizeOverride.m_nValue[ 1 ];
+ return;
+ }
+ // NOTE: This is equal to the viewport size by default,
+ // but other embedded panels can be used
+ x = m_WorkSpaceInsets[0];
+ y = m_WorkSpaceInsets[1];
+ g_pVGuiPanel->GetSize(m_pEmbeddedPanel, iWide, iTall);
+
+ iWide -= m_WorkSpaceInsets[2];
+ iTall -= m_WorkSpaceInsets[3];
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetWorkspaceInsets( int left, int top, int right, int bottom )
+{
+ m_WorkSpaceInsets[0] = left;
+ m_WorkSpaceInsets[1] = top;
+ m_WorkSpaceInsets[2] = right;
+ m_WorkSpaceInsets[3] = bottom;
+}
+
+//-----------------------------------------------------------------------------
+// A bunch of methods needed for the windows version only
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetAsTopMost(VPANEL panel, bool state)
+{
+}
+
+void CMatSystemSurface::SetAsToolBar(VPANEL panel, bool state) // removes the window's task bar entry (for context menu's, etc.)
+{
+}
+
+void CMatSystemSurface::SetForegroundWindow (VPANEL panel)
+{
+ BringToFront(panel);
+}
+
+void CMatSystemSurface::SetPanelVisible(VPANEL panel, bool state)
+{
+}
+
+void CMatSystemSurface::SetMinimized(VPANEL panel, bool state)
+{
+ if (state)
+ {
+ g_pVGuiPanel->SetPlat(panel, VPANEL_MINIMIZED);
+ g_pVGuiPanel->SetVisible(panel, false);
+ }
+ else
+ {
+ g_pVGuiPanel->SetPlat(panel, VPANEL_NORMAL);
+ }
+}
+
+bool CMatSystemSurface::IsMinimized(vgui::VPANEL panel)
+{
+ return (g_pVGuiPanel->Plat(panel) == VPANEL_MINIMIZED);
+
+}
+
+void CMatSystemSurface::FlashWindow(VPANEL panel, bool state)
+{
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetTitle(VPANEL panel, const wchar_t *title)
+{
+ int entry = GetTitleEntry( panel );
+ if ( entry == -1 )
+ {
+ entry = m_Titles.AddToTail();
+ }
+
+ TitleEntry *e = &m_Titles[ entry ];
+ Assert( e );
+ wcsncpy( e->title, title, sizeof( e->title )/ sizeof( wchar_t ) );
+ e->panel = panel;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+wchar_t const *CMatSystemSurface::GetTitle( VPANEL panel )
+{
+ int entry = GetTitleEntry( panel );
+ if ( entry != -1 )
+ {
+ TitleEntry *e = &m_Titles[ entry ];
+ return e->title;
+ }
+
+ return NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Private lookup method
+// Input : *panel -
+// Output : TitleEntry
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetTitleEntry( vgui::VPANEL panel )
+{
+ for ( int i = 0; i < m_Titles.Count(); i++ )
+ {
+ TitleEntry* entry = &m_Titles[ i ];
+ if ( entry->panel == panel )
+ return i;
+ }
+ return -1;
+}
+
+void CMatSystemSurface::SwapBuffers(VPANEL panel)
+{
+}
+
+void CMatSystemSurface::Invalidate(VPANEL panel)
+{
+}
+
+void CMatSystemSurface::ApplyChanges()
+{
+}
+
+// notify icons?!?
+VPANEL CMatSystemSurface::GetNotifyPanel()
+{
+ return NULL;
+}
+
+void CMatSystemSurface::SetNotifyIcon(VPANEL context, HTexture icon, VPANEL panelToReceiveMessages, const char *text)
+{
+}
+
+bool CMatSystemSurface::IsWithin(int x, int y)
+{
+ return true;
+}
+
+bool CMatSystemSurface::ShouldPaintChildPanel(VPANEL childPanel)
+{
+ if ( m_pRestrictedPanel && ( m_pRestrictedPanel != childPanel ) &&
+ !g_pVGuiPanel->HasParent( childPanel, m_pRestrictedPanel ) )
+ {
+ return false;
+ }
+
+ bool isPopup = ipanel()->IsPopup(childPanel);
+ return !isPopup;
+}
+
+bool CMatSystemSurface::RecreateContext(VPANEL panel)
+{
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+// Focus-related methods
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::HasFocus()
+{
+ return true;
+}
+
+void CMatSystemSurface::BringToFront(VPANEL panel)
+{
+ // move panel to top of list
+ g_pVGuiPanel->MoveToFront(panel);
+
+ // move panel to top of popup list
+ if ( g_pVGuiPanel->IsPopup( panel ) )
+ {
+ MovePopupToFront( panel );
+ }
+}
+
+
+// engine-only focus handling (replacing WM_FOCUS windows handling)
+void CMatSystemSurface::SetTopLevelFocus(VPANEL pSubFocus)
+{
+ // walk up the hierarchy until we find what popup panel belongs to
+ while (pSubFocus)
+ {
+ if (ipanel()->IsPopup(pSubFocus) && ipanel()->IsMouseInputEnabled(pSubFocus))
+ {
+ BringToFront(pSubFocus);
+ break;
+ }
+
+ pSubFocus = ipanel()->GetParent(pSubFocus);
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Installs a function to play sounds
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InstallPlaySoundFunc( PlaySoundFunc_t soundFunc )
+{
+ m_PlaySoundFunc = soundFunc;
+}
+
+
+//-----------------------------------------------------------------------------
+// plays a sound
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PlaySound(const char *pFileName)
+{
+ if (m_PlaySoundFunc)
+ m_PlaySoundFunc( pFileName );
+}
+
+
+//-----------------------------------------------------------------------------
+// handles mouse movement
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetCursorPos(int x, int y)
+{
+ CursorSetPos( m_HWnd, x, y );
+}
+
+void CMatSystemSurface::GetCursorPos(int &x, int &y)
+{
+ CursorGetPos( m_HWnd, x, y );
+}
+
+void CMatSystemSurface::SetCursor(HCursor hCursor)
+{
+ if ( IsCursorLocked() )
+ return;
+
+ if ( _currentCursor != hCursor )
+ {
+ _currentCursor = hCursor;
+ CursorSelect( hCursor );
+ }
+}
+
+void CMatSystemSurface::EnableMouseCapture( VPANEL panel, bool state )
+{
+#ifdef WIN32
+ if ( state )
+ {
+ ::SetCapture( reinterpret_cast< HWND >( m_HWnd ) );
+ }
+ else
+ {
+ ::ReleaseCapture();
+ }
+#elif defined( POSIX )
+ // SetCapture on Win32 makes all the mouse messages (move and button up/down) head to
+ // the captured window. From what I can tell, this routine is called for modal dialogs
+ // when you click down on a button. However the current behavior is to highlight the
+ // buttons when you're over them, and trigger when you mouse up over the top - so I
+ // don't believe that SetCapture is needed on Windows, and Linux is behaving exactly
+ // the same as Win32 in all the tests I've run so far. (I've clicked on a lot of dialogs).
+ // I talked with Alfred about this and we haven't done any SetCapture stuff on OSX ever
+ // and he says nobody has ever reported any regressions.
+ // So I've removed the Assert. 8/32/2012 - mikesart.
+#else
+#error
+#endif
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Turns the panel into a standalone window
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::CreatePopup(VPANEL panel, bool minimized, bool showTaskbarIcon, bool disabled , bool mouseInput , bool kbInput)
+{
+ if (!g_pVGuiPanel->GetParent(panel))
+ {
+ g_pVGuiPanel->SetParent(panel, GetEmbeddedPanel());
+ }
+ ((VPanel *)panel)->SetPopup(true);
+ ((VPanel *)panel)->SetKeyBoardInputEnabled(kbInput);
+ ((VPanel *)panel)->SetMouseInputEnabled(mouseInput);
+
+ HPanel p = ivgui()->PanelToHandle( panel );
+
+ if ( m_PopupList.Find( p ) == m_PopupList.InvalidIndex() )
+ {
+ m_PopupList.AddToTail( p );
+ }
+ else
+ {
+ MovePopupToFront( panel );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Create/destroy panels..
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::AddPanel(VPANEL panel)
+{
+ if (g_pVGuiPanel->IsPopup(panel))
+ {
+ // turn it into a popup menu
+ CreatePopup(panel, false);
+ }
+}
+
+void CMatSystemSurface::ReleasePanel(VPANEL panel)
+{
+ // Remove from popup list if needed and remove any dead popups while we're at it
+ RemovePopup( panel );
+
+ int entry = GetTitleEntry( panel );
+ if ( entry != -1 )
+ {
+ m_Titles.Remove( entry );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Popup accessors used by VGUI
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::GetPopupCount( )
+{
+ return m_PopupList.Count();
+}
+
+VPANEL CMatSystemSurface::GetPopup( int index )
+{
+ HPanel p = m_PopupList[ index ];
+ VPANEL panel = ivgui()->HandleToPanel( p );
+ return panel;
+}
+
+void CMatSystemSurface::ResetPopupList( )
+{
+ m_PopupList.RemoveAll();
+}
+
+void CMatSystemSurface::AddPopup( VPANEL panel )
+{
+ HPanel p = ivgui()->PanelToHandle( panel );
+
+ if ( m_PopupList.Find( p ) == m_PopupList.InvalidIndex() )
+ {
+ m_PopupList.AddToTail( p );
+ }
+}
+
+
+void CMatSystemSurface::RemovePopup( vgui::VPANEL panel )
+{
+ // Remove from popup list if needed and remove any dead popups while we're at it
+ int c = GetPopupCount();
+
+ for ( int i = c - 1; i >= 0 ; i-- )
+ {
+ VPANEL popup = GetPopup(i );
+ if ( popup && ( popup != panel ) )
+ continue;
+
+ m_PopupList.Remove( i );
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Methods associated with iterating + drawing the panel tree
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::AddPopupsToList( VPANEL panel )
+{
+ if (!g_pVGuiPanel->IsVisible(panel))
+ return;
+
+ // Add to popup list as we visit popups
+ // Note: popup list is cleared in RunFrame which occurs before this call!!!
+ if ( g_pVGuiPanel->IsPopup( panel ) )
+ {
+ AddPopup( panel );
+ }
+
+ int count = g_pVGuiPanel->GetChildCount(panel);
+ for (int i = 0; i < count; ++i)
+ {
+ VPANEL child = g_pVGuiPanel->GetChild(panel, i);
+ AddPopupsToList( child );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: recurses the panels calculating absolute positions
+// parents must be solved before children
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InternalSolveTraverse(VPANEL panel)
+{
+ VPanel * RESTRICT vp = (VPanel *)panel;
+
+ vp->TraverseLevel( 1 );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - %s", __FUNCTION__, vp->GetName() );
+
+ // solve the parent
+ vp->Solve();
+
+ CUtlVector< VPanel * > &children = vp->GetChildren();
+
+ // WARNING: Some of the think functions add/remove children, so make sure we
+ // explicitly check for children.Count().
+ for ( int i = 0; i < children.Count(); ++i )
+ {
+ VPanel *child = children[ i ];
+ if (child->IsVisible())
+ {
+ InternalSolveTraverse( (VPANEL)child );
+ }
+ }
+
+ vp->TraverseLevel( -1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: recurses the panels giving them a chance to do a user-defined think,
+// PerformLayout and ApplySchemeSettings
+// must be done child before parent
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InternalThinkTraverse(VPANEL panel)
+{
+ VPanel * RESTRICT vp = (VPanel *)panel;
+
+ vp->TraverseLevel( 1 );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - %s", __FUNCTION__, vp->GetName() );
+
+ // think the parent
+ vp->Client()->Think();
+
+ CUtlVector< VPanel * > &children = vp->GetChildren();
+
+ // WARNING: Some of the think functions add/remove children, so make sure we
+ // explicitly check for children.Count().
+ for ( int i = 0; i < children.Count(); ++i )
+ {
+ VPanel *child = children[ i ];
+ if ( child->IsVisible() )
+ {
+ InternalThinkTraverse( (VPANEL)child );
+ }
+ }
+
+ vp->TraverseLevel( -1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: recurses the panels giving them a chance to do apply settings,
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::InternalSchemeSettingsTraverse(VPANEL panel, bool forceApplySchemeSettings)
+{
+ VPanel * RESTRICT vp = (VPanel *)panel;
+
+ vp->TraverseLevel( 1 );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - %s", __FUNCTION__, vp->GetName() );
+
+ CUtlVector< VPanel * > &children = vp->GetChildren();
+
+ // apply to the children...
+ for ( int i = 0; i < children.Count(); ++i )
+ {
+ VPanel *child = children[ i ];
+ if ( forceApplySchemeSettings || child->IsVisible() )
+ {
+ InternalSchemeSettingsTraverse((VPANEL)child, forceApplySchemeSettings);
+ }
+ }
+ // and then the parent
+ vp->Client()->PerformApplySchemeSettings();
+
+ vp->TraverseLevel( -1 );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Walks through the panel tree calling Solve() on them all, in order
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SolveTraverse(VPANEL panel, bool forceApplySchemeSettings)
+{
+ {
+ VPROF( "InternalSchemeSettingsTraverse" );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - InternalSchemeSettingsTraverse", __FUNCTION__ );
+ InternalSchemeSettingsTraverse(panel, forceApplySchemeSettings);
+ }
+
+ {
+ VPROF( "InternalThinkTraverse" );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - InternalThinkTraverse", __FUNCTION__ );
+ InternalThinkTraverse(panel);
+ }
+
+ {
+ VPROF( "InternalSolveTraverse" );
+ tmZone( TELEMETRY_LEVEL1, TMZF_NONE, "%s - InternalSolveTraverse", __FUNCTION__ );
+ InternalSolveTraverse(panel);
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Restricts rendering to a single panel
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::RestrictPaintToSinglePanel(VPANEL panel)
+{
+ if ( panel && m_pRestrictedPanel && m_pRestrictedPanel == input()->GetAppModalSurface() )
+ {
+ return; // don't restrict drawing to a panel other than the modal one - that's a good way to hang the game.
+ }
+
+ m_pRestrictedPanel = panel;
+
+ if ( !input()->GetAppModalSurface() )
+ {
+ input()->SetAppModalSurface( panel ); // if painting is restricted to this panel, it had better be modal, or else you can get in some bad state...
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Is a panel under the restricted panel?
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::IsPanelUnderRestrictedPanel( VPANEL panel )
+{
+ if ( !m_pRestrictedPanel )
+ return true;
+
+ while ( panel )
+ {
+ if ( panel == m_pRestrictedPanel )
+ return true;
+
+ panel = ipanel()->GetParent( panel );
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Main entry point for painting
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PaintTraverseEx(VPANEL panel, bool paintPopups /*= false*/ )
+{
+ MAT_FUNC;
+
+ if ( !ipanel()->IsVisible( panel ) )
+ return;
+
+ VPROF( "CMatSystemSurface::PaintTraverse" );
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ bool bTopLevelDraw = false;
+
+ if ( g_bInDrawing == false )
+ {
+ // only set the 2d ortho mode once
+ bTopLevelDraw = true;
+ StartDrawing();
+
+ // clear z + stencil buffer
+ // NOTE: Stencil is used to get 3D painting in vgui panels working correctly
+ pRenderContext->ClearBuffers( false, true, true );
+ pRenderContext->SetStencilEnable( true );
+ pRenderContext->SetStencilFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilZFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilPassOperation( STENCILOPERATION_REPLACE );
+ pRenderContext->SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_GREATEREQUAL );
+ pRenderContext->SetStencilReferenceValue( 0 );
+ pRenderContext->SetStencilTestMask( 0xFFFFFFFF );
+ pRenderContext->SetStencilWriteMask( 0xFFFFFFFF );
+ }
+
+ float flOldZPos = m_flZPos;
+
+ // NOTE You might expect we'd have to draw these under the popups so they would occlude
+ // them, but there are a few things we do have to draw on top of, esp. the black
+ // panel that draws over the top of the engine to darken everything.
+ m_flZPos = 0.0f;
+ if ( panel == GetEmbeddedPanel() )
+ {
+ if ( m_pRestrictedPanel )
+ {
+ // Paint the restricted panel, and its parent.
+ // NOTE: This call has guards to not draw popups. If the restricted panel
+ // is a popup, it won't draw here.
+ ipanel()->PaintTraverse( ipanel()->GetParent( m_pRestrictedPanel ), true );
+ }
+ else
+ {
+ // paint traverse the root panel, painting all children
+ VPROF( "ipanel()->PaintTraverse" );
+ ipanel()->PaintTraverse( panel, true );
+ }
+ }
+ else
+ {
+ // If it's a popup, it should already have been painted above
+ VPROF( "ipanel()->PaintTraverse" );
+ if ( !paintPopups || !ipanel()->IsPopup( panel ) )
+ {
+ ipanel()->PaintTraverse( panel, true );
+ }
+ }
+
+ // draw the popups
+ if ( paintPopups )
+ {
+ // now draw the popups front to back
+ // since depth-test and depth-write are on, the front panels will occlude the underlying ones
+ {
+ VPROF( "CMatSystemSurface::PaintTraverse popups loop" );
+ int popups = GetPopupCount();
+ if ( popups > 254 )
+ {
+ Warning( "Too many popups! Rendering will be bad!\n" );
+ }
+
+ // HACK! Using stencil ref 254 so drag/drop helper can use 255.
+ int nStencilRef = 254;
+ for ( int i = popups - 1; i >= 0; --i )
+ {
+ VPANEL popupPanel = GetPopup( i );
+
+ if ( !popupPanel )
+ continue;
+
+ if ( !ipanel()->IsFullyVisible( popupPanel ) )
+ continue;
+
+ if ( !IsPanelUnderRestrictedPanel( popupPanel ) )
+ continue;
+
+ // This makes sure the drag/drop helper is always the first thing drawn
+ bool bIsTopmostPopup = ( (VPanel *)popupPanel )->IsTopmostPopup();
+
+ // set our z position
+ pRenderContext->SetStencilReferenceValue( bIsTopmostPopup ? 255 : nStencilRef );
+ --nStencilRef;
+
+ m_flZPos = ((float)(i) / (float)popups);
+ ipanel()->PaintTraverse( popupPanel, true );
+ }
+ }
+ }
+
+ // Restore the old Z Pos
+ m_flZPos = flOldZPos;
+
+ if ( bTopLevelDraw )
+ {
+ // only undo the 2d ortho mode once
+ VPROF( "FinishDrawing" );
+
+ // Reset stencil to normal state
+ pRenderContext->SetStencilEnable( false );
+
+ FinishDrawing();
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Draw a panel
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PaintTraverse(VPANEL panel)
+{
+ PaintTraverseEx( panel, false );
+}
+
+
+//-----------------------------------------------------------------------------
+// Begins, ends 3D painting from within a panel paint() method
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom, bool bRenderToTexture )
+{
+ MAT_FUNC;
+
+ if ( IsX360() )
+ {
+ Assert( 0 );
+ return;
+ }
+
+ Assert( iRight > iLeft );
+ Assert( iBottom > iTop );
+
+ // Can't use this while drawing in the 3D world since it relies on
+ // whacking the shared depth buffer
+ Assert( !m_bDrawingIn3DWorld );
+ if ( m_bDrawingIn3DWorld )
+ return;
+
+ m_n3DLeft = iLeft;
+ m_n3DRight = iRight;
+ m_n3DTop = iTop;
+ m_n3DBottom = iBottom;
+
+ // Can't use this feature when drawing into the 3D world
+ Assert( !m_bDrawingIn3DWorld );
+ Assert( !m_bIn3DPaintMode );
+ m_bIn3DPaintMode = true;
+ m_b3DPaintRenderToTexture = bRenderToTexture;
+
+ // Save off the matrices in case the painting method changes them.
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PushMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->PushMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PushMatrix();
+
+ if ( bRenderToTexture )
+ {
+
+ // For 3d painting, use the off-screen render target the material system allocates
+ // NOTE: We have to grab it here, as opposed to during init,
+ // because the mode hasn't been set by now.
+ if ( !m_FullScreenBuffer )
+ {
+ m_FullScreenBuffer.Init( materials->FindTexture( m_FullScreenBufferName, "render targets" ) );
+ }
+
+ // FIXME: Set the viewport to match the clip rectangle?
+ // Set the viewport to match the scissor rectangle
+ pRenderContext->PushRenderTargetAndViewport( m_FullScreenBuffer,
+ 0, 0, iRight - iLeft, iBottom - iTop );
+
+ // NOTE: Stencil is used to get 3D painting in vgui panels working correctly
+ pRenderContext->SetStencilFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilZFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilPassOperation( STENCILOPERATION_REPLACE );
+ pRenderContext->SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_EQUAL );
+
+ // Don't draw the 3D scene w/ stencil
+ pRenderContext->SetStencilEnable( false );
+ }
+ else
+ {
+ int clipLeft, clipTop, clipRight, clipBottom;
+ bool clipEnabled;
+ GetScissorRect( clipLeft, clipTop, clipRight, clipBottom, clipEnabled );
+ pRenderContext->PushRenderTargetAndViewport();
+ pRenderContext->Viewport( clipLeft + iLeft, clipTop + iTop, iRight - iLeft, iBottom - iTop );
+ }
+
+ pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
+
+ pRenderContext->Flush();
+}
+
+void CMatSystemSurface::End3DPaint()
+{
+ MAT_FUNC;
+
+ if ( IsX360() )
+ {
+ Assert( 0 );
+ return;
+ }
+
+ // Can't use this feature when drawing into the 3D world
+ Assert( !m_bDrawingIn3DWorld );
+ Assert( m_bIn3DPaintMode );
+ m_bIn3DPaintMode = false;
+
+ // Reset stencil to set stencil everywhere we draw
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+
+ pRenderContext->SetStencilEnable( true );
+ pRenderContext->SetStencilFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilZFailOperation( STENCILOPERATION_KEEP );
+ pRenderContext->SetStencilPassOperation( STENCILOPERATION_REPLACE );
+ pRenderContext->SetStencilCompareFunction( STENCILCOMPARISONFUNCTION_GREATEREQUAL );
+
+ // Restore the matrices
+ pRenderContext->MatrixMode( MATERIAL_MODEL );
+ pRenderContext->PopMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_VIEW );
+ pRenderContext->PopMatrix();
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PopMatrix();
+
+ // Restore the viewport (it was stored off in StartDrawing)
+ pRenderContext->PopRenderTargetAndViewport();
+ pRenderContext->CullMode(MATERIAL_CULLMODE_CCW);
+
+ // Draw the full-screen buffer into the panel, if we rendering
+ // to a texture
+ if ( m_b3DPaintRenderToTexture )
+ DrawFullScreenBuffer( m_n3DLeft, m_n3DTop, m_n3DRight, m_n3DBottom );
+
+ // ReSet the material state
+ InternalSetMaterial( NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+// skin composition, force drawing
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::BeginSkinCompositionPainting()
+{
+ g_bInDrawing = true;
+}
+
+
+//-----------------------------------------------------------------------------
+// end drawing when finish skin composition
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::EndSkinCompositionPainting()
+{
+ g_bInDrawing = false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Gets texture coordinates for drawing the full screen buffer
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetFullScreenTexCoords( int x, int y, int w, int h, float *pMinU, float *pMinV, float *pMaxU, float *pMaxV )
+{
+ int nTexWidth = m_FullScreenBuffer->GetActualWidth();
+ int nTexHeight = m_FullScreenBuffer->GetActualHeight();
+ float flOOWidth = 1.0f / nTexWidth;
+ float flOOHeight = 1.0f / nTexHeight;
+
+ *pMinU = ( (float)x + 0.5f ) * flOOWidth;
+ *pMinV = ( (float)y + 0.5f ) * flOOHeight;
+ *pMaxU = ( (float)(x+w) - 0.5f ) * flOOWidth;
+ *pMaxV = ( (float)(y+h) - 0.5f ) * flOOHeight;
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws the fullscreen buffer into the panel
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawFullScreenBuffer( int nLeft, int nTop, int nRight, int nBottom )
+{
+ MAT_FUNC;
+
+ // Draw a textured rectangle over the area
+ if ( m_nFullScreenBufferMaterialId == -1 )
+ {
+ m_nFullScreenBufferMaterialId = CreateNewTextureID();
+ DrawSetTextureMaterial( m_nFullScreenBufferMaterialId, m_FullScreenBufferMaterial );
+ }
+
+ float flGetAlphaMultiplier = DrawGetAlphaMultiplier();
+ unsigned char oldColor[4];
+ oldColor[0] = m_DrawColor[0];
+ oldColor[1] = m_DrawColor[1];
+ oldColor[2] = m_DrawColor[2];
+ oldColor[3] = m_DrawColor[3];
+
+ DrawSetAlphaMultiplier( 1.0f );
+ DrawSetColor( 255, 255, 255, 255 );
+
+ DrawSetTexture( m_nFullScreenBufferMaterialId );
+
+ float u0, u1, v0, v1;
+ GetFullScreenTexCoords( 0, 0, nRight - nLeft, nBottom - nTop, &u0, &v0, &u1, &v1 );
+ DrawTexturedSubRect( nLeft, nTop, nRight, nBottom, u0, v0, u1, v1 );
+
+ m_DrawColor[0] = oldColor[0];
+ m_DrawColor[1] = oldColor[1];
+ m_DrawColor[2] = oldColor[2];
+ m_DrawColor[3] = oldColor[3];
+ DrawSetAlphaMultiplier( flGetAlphaMultiplier );
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws a rectangle, setting z to the current value
+//-----------------------------------------------------------------------------
+float CMatSystemSurface::GetZPos() const
+{
+ return m_flZPos;
+}
+
+
+//-----------------------------------------------------------------------------
+// Some drawing methods that cannot be accomplished under Win32
+//-----------------------------------------------------------------------------
+#define CIRCLE_POINTS 360
+
+void CMatSystemSurface::DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+ // Draw a circle
+ int iDegrees = 0;
+ Vector vecPoint, vecLastPoint(0,0,0);
+ vecPoint.z = 0.0f;
+ Color clr;
+ clr.SetColor( r, g, b, a );
+ DrawSetColor( clr );
+
+ for ( int i = 0; i < CIRCLE_POINTS; i++ )
+ {
+ float flRadians = DEG2RAD( iDegrees );
+ iDegrees += (360 / CIRCLE_POINTS);
+
+ float ca = cos( flRadians );
+ float sa = sin( flRadians );
+
+ // Rotate it around the circle
+ vecPoint.x = centerx + (radius * sa);
+ vecPoint.y = centery - (radius * ca);
+
+ // Draw the point, if it's not on the previous point, to avoid smaller circles being brighter
+ if ( vecLastPoint != vecPoint )
+ {
+ DrawFilledRect( vecPoint.x, vecPoint.y, vecPoint.x + 1, vecPoint.y + 1 );
+ }
+
+ vecLastPoint = vecPoint;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Draws colored text to a vgui panel
+// Input : *font - font to use
+// x - position of text
+// y -
+// r - color of text
+// g -
+// b -
+// a - alpha ( 255 = opaque, 0 = transparent )
+// *fmt - va_* text string
+// ... -
+// Output : int - horizontal # of pixels drawn
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, const char *fmt, va_list argptr )
+{
+ MAT_FUNC;
+ Assert( g_bInDrawing );
+ int len;
+ char data[1024];
+
+ DrawSetTextPos( x, y );
+ DrawSetTextColor( r, g, b, a );
+
+ len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
+
+ DrawSetTextFont( font );
+
+ wchar_t szconverted[ 1024 ];
+ g_pVGuiLocalize->ConvertANSIToUnicode( data, szconverted, 1024 );
+ DrawPrintText( szconverted, wcslen(szconverted ) );
+
+ int totalLength = DrawTextLen( font, data );
+
+ return x + totalLength;
+}
+
+int CMatSystemSurface::DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, const char *fmt, ... )
+{
+ MAT_FUNC;
+
+ va_list argptr;
+ va_start( argptr, fmt );
+ int ret = DrawColoredText( font, x, y, r, g, b, a, fmt, argptr );
+ va_end(argptr);
+ return ret;
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws text with current font at position and wordwrapped to the rect using color values specified
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SearchForWordBreak( vgui::HFont font, char *text, int& chars, int& pixels )
+{
+ chars = pixels = 0;
+ while ( 1 )
+ {
+ char ch = text[ chars ];
+ int a, b, c;
+ GetCharABCwide( font, ch, a, b, c );
+
+ if ( ch == 0 || ch <= 32 )
+ {
+ if ( ch == 32 && chars == 0 )
+ {
+ pixels += ( b + c );
+ chars++;
+ }
+ break;
+ }
+
+ pixels += ( b + c );
+ chars++;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: If text width is specified, reterns height of text at that width
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawTextHeight( vgui::HFont font, int w, int& h, const char *fmt, ... )
+{
+ if ( !font )
+ return;
+
+ int len;
+ char data[8192];
+
+ va_list argptr;
+ va_start( argptr, fmt );
+ len = Q_vsnprintf( data, sizeof( data ), fmt, argptr );
+ va_end( argptr );
+
+ int x = 0;
+ int y = 0;
+
+ int ystep = GetFontTall( font );
+ int startx = x;
+ int endx = x + w;
+ //int endy = y + h;
+ int endy = 0;
+
+ int chars = 0;
+ int pixels = 0;
+ for ( int i = 0 ; i < len; i += chars )
+ {
+ SearchForWordBreak( font, &data[ i ], chars, pixels );
+
+ if ( data[ i ] == '\n' )
+ {
+ x = startx;
+ y += ystep;
+ chars = 1;
+ continue;
+ }
+
+ if ( x + ( pixels ) >= endx )
+ {
+ x = startx;
+ // No room even on new line!!!
+ if ( x + pixels >= endx )
+ break;
+
+ y += ystep;
+ }
+
+ for ( int j = 0 ; j < chars; j++ )
+ {
+ int a, b, c;
+ char ch = data[ i + j ];
+
+ GetCharABCwide( font, ch, a, b, c );
+
+ x += a + b + c;
+ }
+ }
+
+ endy = y+ystep;
+
+ h = endy;
+}
+
+
+//-----------------------------------------------------------------------------
+// Draws text with current font at position and wordwrapped to the rect using color values specified
+//-----------------------------------------------------------------------------
+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, ... )
+{
+ MAT_FUNC;
+
+ Assert( g_bInDrawing );
+ if ( !font )
+ return;
+
+ int len;
+ char data[8192];
+
+ va_list argptr;
+ va_start( argptr, fmt );
+ len = Q_vsnprintf( data, sizeof( data ), fmt, argptr );
+ va_end( argptr );
+
+ DrawSetTextPos( x, y );
+ DrawSetTextColor( r, g, b, a );
+ DrawSetTextFont( font );
+
+ int ystep = GetFontTall( font );
+ int startx = x;
+ int endx = x + w;
+ int endy = y + h;
+
+ int chars = 0;
+ int pixels = 0;
+
+ char word[ 512 ];
+ char space[ 2 ];
+ space[1] = 0;
+ space[0] = ' ';
+
+ for ( int i = 0 ; i < len; i += chars )
+ {
+ SearchForWordBreak( font, &data[ i ], chars, pixels );
+
+ if ( data[ i ] == '\n' )
+ {
+ x = startx;
+ y += ystep;
+ chars = 1;
+ continue;
+ }
+
+ if ( x + ( pixels ) >= endx )
+ {
+ x = startx;
+ // No room even on new line!!!
+ if ( x + pixels >= endx )
+ break;
+
+ y += ystep;
+ }
+
+ if ( y + ystep >= endy )
+ break;
+
+
+ if ( chars <= 0 )
+ continue;
+
+ Q_strncpy( word, &data[ i ], chars + 1 );
+
+ DrawSetTextPos( x, y );
+
+ wchar_t szconverted[ 1024 ];
+ g_pVGuiLocalize->ConvertANSIToUnicode( word, szconverted, 1024 );
+ DrawPrintText( szconverted, wcslen(szconverted ) );
+
+ // Leave room for space, too
+ x += DrawTextLen( font, word );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Determine length of text string
+//-----------------------------------------------------------------------------
+int CMatSystemSurface::DrawTextLen( vgui::HFont font, const char *fmt, ... )
+{
+ va_list argptr;
+ char data[1024];
+ int len;
+
+ va_start(argptr, fmt);
+ len = Q_vsnprintf(data, sizeof( data ), fmt, argptr);
+ va_end(argptr);
+
+ int i;
+ int x = 0;
+
+ for ( i = 0 ; i < len; i++ )
+ {
+ int a, b, c;
+ GetCharABCwide( font, data[i], a, b, c );
+
+ // Ignore a
+ // x += a;
+ x += b;
+ x += c;
+ }
+
+ return x;
+}
+
+//-----------------------------------------------------------------------------
+// Disable clipping during rendering
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DisableClipping( bool bDisable )
+{
+ // when the clipping rules change. flush any text we've
+ // queued up to draw so it gets clipped appropriatesly
+ DrawFlushText();
+
+ EnableScissor( !bDisable );
+}
+
+
+//-----------------------------------------------------------------------------
+// Fetch current clipping rectangle
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetClippingRect( int &left, int &top, int &right, int &bottom, bool &bClippingDisabled )
+{
+ bool bEnabled = true;
+ GetScissorRect( left, top, right, bottom, bEnabled );
+ bClippingDisabled = !bEnabled;
+}
+
+//-----------------------------------------------------------------------------
+// Set clipping rectangle
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetClippingRect( int left, int top, int right, int bottom )
+{
+ SetScissorRect( left, top, right, bottom );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: unlocks the cursor state
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::IsCursorLocked() const
+{
+ return ::IsCursorLocked();
+}
+
+
+//-----------------------------------------------------------------------------
+// Sets the mouse Get + Set callbacks
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetMouseCallbacks( GetMouseCallback_t GetFunc, SetMouseCallback_t SetFunc )
+{
+ // FIXME: Remove! This is obsolete
+ Assert(0);
+}
+
+
+//-----------------------------------------------------------------------------
+// Tells the surface to ignore windows messages
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::EnableWindowsMessages( bool bEnable )
+{
+ EnableInput( bEnable );
+}
+
+void CMatSystemSurface::MovePopupToFront(VPANEL panel)
+{
+ HPanel p = ivgui()->PanelToHandle( panel );
+
+ int index = m_PopupList.Find( p );
+ if ( index == m_PopupList.InvalidIndex() )
+ return;
+
+ m_PopupList.Remove( index );
+ m_PopupList.AddToTail( p );
+
+ if ( g_bSpewFocus )
+ {
+ char const *pName = ipanel()->GetName( panel );
+ Msg( "%s moved to front\n", pName ? pName : "(no name)" );
+ }
+
+ // If the modal panel isn't a parent, restore it to the top, to prevent a hard lock
+ if ( input()->GetAppModalSurface() )
+ {
+ if ( !g_pVGuiPanel->HasParent(panel, input()->GetAppModalSurface()) )
+ {
+ HPanel p = ivgui()->PanelToHandle( input()->GetAppModalSurface() );
+ index = m_PopupList.Find( p );
+ if ( index != m_PopupList.InvalidIndex() )
+ {
+ m_PopupList.Remove( index );
+ m_PopupList.AddToTail( p );
+ }
+ }
+ }
+
+ ivgui()->PostMessage(panel, new KeyValues("OnMovedPopupToFront"), NULL);
+}
+
+void CMatSystemSurface::MovePopupToBack(VPANEL panel)
+{
+ HPanel p = ivgui()->PanelToHandle( panel );
+
+ int index = m_PopupList.Find( p );
+ if ( index == m_PopupList.InvalidIndex() )
+ {
+ return;
+ }
+
+ m_PopupList.Remove( index );
+ m_PopupList.AddToHead( p );
+}
+
+
+bool CMatSystemSurface::IsInThink( VPANEL panel)
+{
+ if ( m_bInThink )
+ {
+ if ( panel == m_CurrentThinkPanel ) // HasParent() returns true if you pass yourself in
+ {
+ return false;
+ }
+
+ return ipanel()->HasParent( panel, m_CurrentThinkPanel);
+ }
+ return false;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+bool CMatSystemSurface::IsCursorVisible()
+{
+ return m_cursorAlwaysVisible || (_currentCursor != dc_none);
+}
+
+void CMatSystemSurface::SetCursorAlwaysVisible( bool visible )
+{
+ m_cursorAlwaysVisible = visible;
+ CursorSelect( visible ? dc_alwaysvisible_push : dc_alwaysvisible_pop );
+}
+
+bool CMatSystemSurface::IsTextureIDValid(int id)
+{
+ // FIXME:
+ return true;
+}
+
+void CMatSystemSurface::SetAllowHTMLJavaScript( bool state )
+{
+ m_bAllowJavaScript = state;
+}
+
+IHTML *CMatSystemSurface::CreateHTMLWindow(vgui::IHTMLEvents *events,VPANEL context)
+{
+ Assert( !"CMatSystemSurface::CreateHTMLWindow" );
+ return NULL;
+}
+
+
+void CMatSystemSurface::DeleteHTMLWindow(IHTML *htmlwin)
+{
+}
+
+
+
+void CMatSystemSurface::PaintHTMLWindow(IHTML *htmlwin)
+{
+}
+
+bool CMatSystemSurface::BHTMLWindowNeedsPaint(IHTML *htmlwin)
+{
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+/*void CMatSystemSurface::DrawSetTextureRGBA( int id, const unsigned char* rgba, int wide, int tall )
+{
+ TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, IMAGE_FORMAT_RGBA8888 );
+}*/
+
+void CMatSystemSurface::DrawSetTextureRGBA(int id, const unsigned char* rgba, int wide, int tall, int hardwareFilter, bool forceUpload)
+{
+ TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, IMAGE_FORMAT_RGBA8888, false );
+}
+
+void CMatSystemSurface::DrawSetTextureRGBAEx( int id, const unsigned char* rgba, int wide, int tall, ImageFormat format )
+{
+ TextureDictionary()->SetTextureRGBAEx( id, (const char *)rgba, wide, tall, format, true );
+}
+
+void CMatSystemSurface::DrawSetSubTextureRGBA(int textureID, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall)
+{
+ TextureDictionary()->SetSubTextureRGBA( textureID, drawX, drawY, rgba, subTextureWide, subTextureTall );
+}
+
+void CMatSystemSurface::DrawUpdateRegionTextureRGBA( int nTextureID, int x, int y, const unsigned char *pchData, int wide, int tall, ImageFormat imageFormat )
+{
+ TextureDictionary()->UpdateSubTextureRGBA( nTextureID, x, y, pchData, wide, tall, imageFormat );
+}
+
+void CMatSystemSurface::SetModalPanel(VPANEL )
+{
+}
+
+VPANEL CMatSystemSurface::GetModalPanel()
+{
+ return 0;
+}
+
+void CMatSystemSurface::UnlockCursor()
+{
+ ::LockCursor( false );
+}
+
+void CMatSystemSurface::LockCursor()
+{
+ ::LockCursor( true );
+}
+
+void CMatSystemSurface::SetTranslateExtendedKeys(bool state)
+{
+}
+
+VPANEL CMatSystemSurface::GetTopmostPopup()
+{
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: gets the absolute coordinates of the screen (in screen space)
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall)
+{
+ // always work in full window screen space
+ x = 0;
+ y = 0;
+ GetScreenSize(wide, tall);
+}
+
+// returns true if the specified panel is a child of the current modal panel
+// if no modal panel is set, then this always returns TRUE
+static bool IsChildOfModalSubTree(VPANEL panel)
+{
+ if ( !panel )
+ return true;
+
+ VPANEL modalSubTree = input()->GetModalSubTree();
+
+ if ( modalSubTree )
+ {
+ bool restrictMessages = input()->ShouldModalSubTreeReceiveMessages();
+
+ // If panel is child of modal subtree, the allow messages to route to it if restrict messages is set
+ bool isChildOfModal = ipanel()->HasParent( panel, modalSubTree );
+ if ( isChildOfModal )
+ {
+ return restrictMessages;
+ }
+ // If panel is not a child of modal subtree, then only allow messages if we're not restricting them to the modal subtree
+ else
+ {
+ return !restrictMessages;
+ }
+ }
+
+ return true;
+}
+
+void CMatSystemSurface::CalculateMouseVisible()
+{
+ int i;
+ m_bNeedsMouse = false;
+ m_bNeedsKeyboard = false;
+
+ if ( input()->GetMouseCapture() != 0 )
+ return;
+
+ int c = surface()->GetPopupCount();
+
+ VPANEL modalSubTree = input()->GetModalSubTree();
+ if ( modalSubTree )
+ {
+ for (i = 0 ; i < c ; i++ )
+ {
+ VPanel *pop = (VPanel *)surface()->GetPopup(i) ;
+ bool isChildOfModalSubPanel = IsChildOfModalSubTree( (VPANEL)pop );
+ if ( !isChildOfModalSubPanel )
+ continue;
+
+ bool isVisible=pop->IsVisible();
+ VPanel *p= pop->GetParent();
+
+ while (p && isVisible)
+ {
+ if( p->IsVisible()==false)
+ {
+ isVisible=false;
+ break;
+ }
+ p=p->GetParent();
+ }
+
+ if ( isVisible )
+ {
+ m_bNeedsMouse = m_bNeedsMouse || pop->IsMouseInputEnabled();
+ m_bNeedsKeyboard = m_bNeedsKeyboard || pop->IsKeyBoardInputEnabled();
+
+ // Seen enough!!!
+ if ( m_bNeedsMouse && m_bNeedsKeyboard )
+ break;
+ }
+ }
+ }
+ else
+ {
+ for (i = 0 ; i < c ; i++ )
+ {
+ VPanel *pop = (VPanel *)surface()->GetPopup(i) ;
+
+ bool isVisible=pop->IsVisible();
+ VPanel *p= pop->GetParent();
+
+ while (p && isVisible)
+ {
+ if( p->IsVisible()==false)
+ {
+ isVisible=false;
+ break;
+ }
+ p=p->GetParent();
+ }
+
+ if ( isVisible )
+ {
+ m_bNeedsMouse = m_bNeedsMouse || pop->IsMouseInputEnabled();
+ m_bNeedsKeyboard = m_bNeedsKeyboard || pop->IsKeyBoardInputEnabled();
+
+ // Seen enough!!!
+ if ( m_bNeedsMouse && m_bNeedsKeyboard )
+ break;
+ }
+ }
+ }
+
+ if (m_bNeedsMouse)
+ {
+ // NOTE: We must unlock the cursor *before* the set call here.
+ // Failing to do this causes s_bCursorVisible to not be set correctly
+ // (UnlockCursor fails to set it correctly)
+ UnlockCursor();
+ if ( _currentCursor == vgui::dc_none )
+ {
+ SetCursor(vgui::dc_arrow);
+ }
+ }
+ else
+ {
+ SetCursor(vgui::dc_none);
+ LockCursor();
+ }
+}
+
+bool CMatSystemSurface::NeedKBInput()
+{
+ return m_bNeedsKeyboard;
+}
+
+void CMatSystemSurface::SurfaceGetCursorPos(int &x, int &y)
+{
+ GetCursorPos( x, y );
+}
+void CMatSystemSurface::SurfaceSetCursorPos(int x, int y)
+{
+ SetCursorPos( x, y );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: global alpha setting functions
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::DrawSetAlphaMultiplier( float alpha /* [0..1] */ )
+{
+ m_flAlphaMultiplier = clamp(alpha, 0.0f, 1.0f);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: data accessor
+//-----------------------------------------------------------------------------
+float CMatSystemSurface::DrawGetAlphaMultiplier()
+{
+ return m_flAlphaMultiplier;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *curOrAniFile -
+// Output : vgui::HCursor
+//-----------------------------------------------------------------------------
+vgui::HCursor CMatSystemSurface::CreateCursorFromFile( char const *curOrAniFile, char const *pPathID )
+{
+ return Cursor_CreateCursorFromFile( curOrAniFile, pPathID );
+}
+
+void CMatSystemSurface::SetPanelForInput( VPANEL vpanel )
+{
+ g_pIInput->AssociatePanelWithInputContext( DEFAULT_INPUT_CONTEXT, vpanel );
+ if ( vpanel )
+ {
+ m_bNeedsKeyboard = true;
+ }
+ else
+ {
+ m_bNeedsKeyboard = false;
+ }
+}
+
+#if defined( WIN32 ) && !defined( _X360 )
+static bool GetIconSize( ICONINFO& iconInfo, int& w, int& h )
+{
+ w = h = 0;
+
+ HBITMAP bitmap = iconInfo.hbmColor;
+ BITMAP bm;
+ if ( 0 == GetObject((HGDIOBJ)bitmap, sizeof(BITMAP), (LPVOID)&bm) )
+ {
+ return false;
+ }
+
+ w = bm.bmWidth;
+ h = bm.bmHeight;
+
+ return true;
+}
+
+// If rgba is NULL, bufsize gets filled in w/ # of bytes required
+static bool GetIconBits( HDC hdc, ICONINFO& iconInfo, int& w, int& h, unsigned char *rgba, size_t& bufsize )
+{
+ if ( !iconInfo.hbmColor || !iconInfo.hbmMask )
+ return false;
+
+ if ( !rgba )
+ {
+ if ( !GetIconSize( iconInfo, w, h ) )
+ return false;
+
+ bufsize = (size_t)( ( w * h ) << 2 );
+ return true;
+ }
+
+ bool bret = false;
+
+ Assert( w > 0 );
+ Assert( h > 0 );
+ Assert( bufsize == (size_t)( ( w * h ) << 2 ) );
+
+ DWORD *maskData = new DWORD[ w * h ];
+ DWORD *colorData = new DWORD[ w * h ];
+ DWORD *output = (DWORD *)rgba;
+
+ BITMAPINFO bmInfo;
+
+ memset( &bmInfo, 0, sizeof( bmInfo ) );
+ bmInfo.bmiHeader.biSize = sizeof( bmInfo.bmiHeader );
+ bmInfo.bmiHeader.biWidth = w;
+ bmInfo.bmiHeader.biHeight = h;
+ bmInfo.bmiHeader.biPlanes = 1;
+ bmInfo.bmiHeader.biBitCount = 32;
+ bmInfo.bmiHeader.biCompression = BI_RGB;
+
+ // Get the info about the bits
+ if ( GetDIBits( hdc, iconInfo.hbmMask, 0, h, maskData, &bmInfo, DIB_RGB_COLORS ) == h &&
+ GetDIBits( hdc, iconInfo.hbmColor, 0, h, colorData, &bmInfo, DIB_RGB_COLORS ) == h )
+ {
+ bret = true;
+
+ for ( int row = 0; row < h; ++row )
+ {
+ // Invert
+ int r = ( h - row - 1 );
+ int rowstart = r * w;
+
+ DWORD *color = &colorData[ rowstart ];
+ DWORD *mask = &maskData[ rowstart ];
+ DWORD *outdata = &output[ row * w ];
+
+ for ( int col = 0; col < w; ++col )
+ {
+ unsigned char *cr = ( unsigned char * )&color[ col ];
+
+ // Set alpha
+ cr[ 3 ] = mask[ col ] == 0 ? 0xff : 0x00;
+
+ // Swap blue and red
+ unsigned char t = cr[ 2 ];
+ cr[ 2 ] = cr[ 0 ];
+ cr[ 0 ] = t;
+
+ *( unsigned int *)&outdata[ col ] = *( unsigned int * )cr;
+ }
+ }
+ }
+
+ delete[] colorData;
+ delete[] maskData;
+
+ return bret;
+}
+
+static bool ShouldMakeUnique( char const *extension )
+{
+ if ( !Q_stricmp( extension, "cur" ) )
+ return true;
+ if ( !Q_stricmp( extension, "ani" ) )
+ return true;
+ return false;
+}
+#endif // !_X360
+
+vgui::IImage *CMatSystemSurface::GetIconImageForFullPath( char const *pFullPath )
+{
+ vgui::IImage *newIcon = NULL;
+
+#if defined( WIN32 ) && !defined( _X360 )
+ SHFILEINFO info = { 0 };
+ DWORD_PTR dwResult = SHGetFileInfo(
+ pFullPath,
+ 0,
+ &info,
+ sizeof( info ),
+ SHGFI_TYPENAME | SHGFI_ICON | SHGFI_SMALLICON | SHGFI_SHELLICONSIZE
+ );
+ if ( dwResult )
+ {
+ if ( info.szTypeName[ 0 ] != 0 )
+ {
+ char ext[ 32 ];
+ Q_ExtractFileExtension( pFullPath, ext, sizeof( ext ) );
+
+ char lookup[ 512 ];
+ Q_snprintf( lookup, sizeof( lookup ), "%s", ShouldMakeUnique( ext ) ? pFullPath : info.szTypeName );
+
+ // Now check the dictionary
+ unsigned short idx = m_FileTypeImages.Find( lookup );
+ if ( idx == m_FileTypeImages.InvalidIndex() )
+ {
+ ICONINFO iconInfo;
+ if ( 0 != GetIconInfo( info.hIcon, &iconInfo ) )
+ {
+ int w, h;
+ size_t bufsize = 0;
+
+ HDC hdc = ::GetDC(reinterpret_cast<HWND>(m_HWnd));
+
+ if ( GetIconBits( hdc, iconInfo, w, h, NULL, bufsize ) )
+ {
+ byte *bits = new byte[ bufsize ];
+ if ( bits && GetIconBits( hdc, iconInfo, w, h, bits, bufsize ) )
+ {
+ newIcon = new MemoryBitmap( bits, w, h );
+ }
+ delete[] bits;
+ }
+
+ ::ReleaseDC( reinterpret_cast<HWND>(m_HWnd), hdc );
+ }
+
+ idx = m_FileTypeImages.Insert( lookup, newIcon );
+ }
+
+ newIcon = m_FileTypeImages[ idx ];
+ }
+
+ DestroyIcon( info.hIcon );
+ }
+#endif
+ return newIcon;
+}
+
+const char *CMatSystemSurface::GetResolutionKey( void ) const
+{
+ Assert( !IsPC() );
+ int x, y, width, height;
+ CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
+ pRenderContext->GetViewport( x, y, width, height );
+ if( height <= 480 )
+ {
+ return "_lodef";
+ }
+ else
+ {
+ return "_hidef";
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::Set3DPaintTempRenderTarget( const char *pRenderTargetName )
+{
+ MAT_FUNC;
+
+ Assert( !m_bUsingTempFullScreenBufferMaterial );
+ m_bUsingTempFullScreenBufferMaterial = true;
+
+ InitFullScreenBuffer( pRenderTargetName );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::Reset3DPaintTempRenderTarget( void )
+{
+ MAT_FUNC;
+
+ Assert( m_bUsingTempFullScreenBufferMaterial );
+ m_bUsingTempFullScreenBufferMaterial = false;
+
+ InitFullScreenBuffer( "_rt_FullScreen" );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the origin of the viewport to render into if we were
+// rendering into the frame buffer. This version of the function is
+// mostly here for backward compatibility and always uses a NULL
+// render target (i.e. the frame buffer.)
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetFullscreenViewport( int x, int y, int w, int h )
+{
+ SetFullscreenViewportAndRenderTarget( x, y, w, h, NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Sets the origin of the viewport to render into if we were
+// rendering into the frame buffer. We might actually be generally
+// using a render target but need to switch back to the frame buffer
+// for some panels.
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetFullscreenViewportAndRenderTarget( int x, int y, int w, int h, ITexture *pRenderTarget )
+{
+ m_nFullscreenViewportX = x;
+ m_nFullscreenViewportY = y;
+ m_nFullscreenViewportWidth = w;
+ m_nFullscreenViewportHeight = h;
+ m_pFullscreenRenderTarget = pRenderTarget;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Gets the origin of the viewport to render into if we were
+// rendering into the frame buffer. We might actually be generally
+// using a render target but need to switch back to the frame buffer
+// for some panels.
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::GetFullscreenViewportAndRenderTarget( int & x, int & y, int & w, int & h, ITexture **ppRenderTarget )
+{
+ if( m_nFullscreenViewportHeight == 0 )
+ {
+ // this can't actually be zero. If it is, use the height of the screen instead
+ x = y = 0;
+ GetScreenSize( w, h );
+ if( ppRenderTarget)
+ *ppRenderTarget = NULL;
+ }
+ else
+ {
+ x = m_nFullscreenViewportX;
+ y = m_nFullscreenViewportY;
+ w = m_nFullscreenViewportWidth;
+ h = m_nFullscreenViewportHeight;
+ if( ppRenderTarget)
+ *ppRenderTarget = m_pFullscreenRenderTarget;
+ }
+}
+void CMatSystemSurface::GetFullscreenViewport( int & x, int & y, int & w, int & h )
+{
+ GetFullscreenViewportAndRenderTarget( x, y, w, h, NULL );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle switching in and out of "render to fullscreen" mode. We don't
+// actually support this mode in tools.
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::PushFullscreenViewport()
+{
+ CMatRenderContextPtr pRenderContext( materials );
+
+ // the viewport x/y will be wrong because the render target is only for one eye.
+ // Ask the surface for that information instead.
+ int vx, vy, vw, vh;
+ ITexture *pRenderTarget;
+ GetFullscreenViewportAndRenderTarget( vx, vy, vw, vh, &pRenderTarget );
+ pRenderContext->PushRenderTargetAndViewport( pRenderTarget, NULL, vx, vy, vw, vh );
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PushMatrix();
+ pRenderContext->LoadIdentity();
+ pRenderContext->Scale( 1, -1, 1 );
+
+ //___stop___();
+ pRenderContext->Ortho( g_flPixelOffsetX, g_flPixelOffsetY, vw + g_flPixelOffsetX, vh + g_flPixelOffsetY, -1.0f, 1.0f );
+
+ DisableClipping( true );
+}
+
+void CMatSystemSurface::PopFullscreenViewport()
+{
+ CMatRenderContextPtr pRenderContext( materials );
+
+ pRenderContext->PopRenderTargetAndViewport();
+
+ pRenderContext->MatrixMode( MATERIAL_PROJECTION );
+ pRenderContext->PopMatrix();
+
+ DisableClipping( false );
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Handle switching in and out of "render to fullscreen" mode. We don't
+// actually support this mode in tools.
+//-----------------------------------------------------------------------------
+void CMatSystemSurface::SetSoftwareCursor( bool bUseSoftwareCursor )
+{
+ EnableSoftwareCursor( bUseSoftwareCursor );
+}
+
+void CMatSystemSurface::PaintSoftwareCursor()
+{
+ if( !ShouldDrawSoftwareCursor() )
+ return;
+
+ // this asks Windows for the position RIGHT NOW, which should be the least
+ // latent notion we have of where to draw the cursor
+ int x, y;
+ GetCursorPos( x, y );
+
+ Color clr( 255, 255, 255, 255 );
+
+ float uOffset, vOffset;
+ int nTextureID = GetSoftwareCursorTexture( &uOffset, &vOffset );
+ if( nTextureID <= 0 )
+ return;
+
+ int w, h;
+ DrawGetTextureSize( nTextureID, w, h );
+
+ // the cursors are actually pretty big. Make them smaller.
+ w /= 2;
+ h /= 2;
+
+ int xOffset = (int)(uOffset * (float)w);
+ int yOffset = (int)(vOffset * (float)h);
+
+ Assert( !g_bInDrawing );
+ StartDrawing();
+
+ PaintState_t paintState;
+ paintState.m_iTranslateX = paintState.m_iTranslateY = 0;
+ paintState.m_iScissorLeft = paintState.m_iScissorTop = 0;
+ GetScreenSize( paintState.m_iScissorRight, paintState.m_iScissorBottom );
+
+ SetupPaintState( paintState );
+
+ DrawSetColor( clr );
+ DrawSetTexture( nTextureID );
+ DrawTexturedRect( x + xOffset, y + yOffset, x + xOffset + w, y + yOffset + h );
+ DrawSetTexture(0);
+
+ FinishDrawing();
+}
+
+int CMatSystemSurface::GetTextureNumFrames( int id )
+{
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial( id );
+ if ( !pMaterial )
+ {
+ return 0;
+ }
+ return pMaterial->GetNumAnimationFrames();
+}
+
+void CMatSystemSurface::DrawSetTextureFrame( int id, int nFrame, unsigned int *pFrameCache )
+{
+ IMaterial *pMaterial = TextureDictionary()->GetTextureMaterial( id );
+ if ( !pMaterial )
+ {
+ return;
+ }
+
+ int nTotalFrames = pMaterial->GetNumAnimationFrames();
+ if ( !nTotalFrames )
+ {
+ return;
+ }
+
+ IMaterialVar *pFrameVar = pMaterial->FindVarFast( "$frame", pFrameCache );
+ if ( pFrameVar )
+ {
+ pFrameVar->SetIntValue( nFrame % nTotalFrames );
+ }
+}
diff --git a/vguimatsurface/MatSystemSurface.h b/vguimatsurface/MatSystemSurface.h
new file mode 100644
index 0000000..5be5bf3
--- /dev/null
+++ b/vguimatsurface/MatSystemSurface.h
@@ -0,0 +1,643 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef MATSYSTEMSURFACE_H
+#define MATSYSTEMSURFACE_H
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui/VGUI.h>
+#include <vgui/ISurface.h>
+#include <vgui/IPanel.h>
+#include <vgui/IClientPanel.h>
+#include <vgui_controls/Panel.h>
+#include <vgui/IInput.h>
+#include <vgui_controls/Controls.h>
+#include <vgui/Point.h>
+#include "materialsystem/imaterialsystem.h"
+#include "VGuiMatSurface/IMatSystemSurface.h"
+#include "materialsystem/imesh.h"
+#include "materialsystem/imaterial.h"
+#include "utlvector.h"
+#include "utlsymbol.h"
+#include "materialsystem/MaterialSystemUtil.h"
+#include "tier1/utldict.h"
+#include "tier3/tier3.h"
+
+using namespace vgui;
+
+class IImage;
+
+extern class IMaterialSystem *g_pMaterialSystem;
+//-----------------------------------------------------------------------------
+// The default material system embedded panel
+//-----------------------------------------------------------------------------
+class CMatEmbeddedPanel : public vgui::Panel
+{
+ typedef vgui::Panel BaseClass;
+public:
+ CMatEmbeddedPanel();
+ virtual void OnThink();
+
+ VPANEL IsWithinTraverse(int x, int y, bool traversePopups);
+};
+
+//-----------------------------------------------------------------------------
+//
+// Implementation of the VGUI surface on top of the material system
+//
+//-----------------------------------------------------------------------------
+class CMatSystemSurface : public CTier3AppSystem< IMatSystemSurface >
+{
+ typedef CTier3AppSystem< IMatSystemSurface > BaseClass;
+
+public:
+ CMatSystemSurface();
+ virtual ~CMatSystemSurface();
+
+ // Methods of IAppSystem
+ virtual bool Connect( CreateInterfaceFn factory );
+ virtual void Disconnect();
+ virtual void *QueryInterface( const char *pInterfaceName );
+ virtual InitReturnVal_t Init();
+ virtual void Shutdown();
+
+ // initialization
+ virtual void SetEmbeddedPanel(vgui::VPANEL pEmbeddedPanel);
+
+ // returns true if a panel is minimzed
+ bool IsMinimized(vgui::VPANEL panel);
+
+ // Sets the only panel to draw. Set to NULL to clear.
+ void RestrictPaintToSinglePanel(vgui::VPANEL panel);
+
+ // frame
+ virtual void RunFrame();
+
+ // implementation of vgui::ISurface
+ virtual vgui::VPANEL GetEmbeddedPanel();
+
+ // drawing context
+ virtual void PushMakeCurrent(vgui::VPANEL panel,bool useInSets);
+ virtual void PopMakeCurrent(vgui::VPANEL panel);
+
+ // rendering functions
+ virtual void DrawSetColor(int r,int g,int b,int a);
+ virtual void DrawSetColor(Color col);
+
+ virtual void DrawLine( int x0, int y0, int x1, int y1 );
+ virtual void DrawTexturedLine( const vgui::Vertex_t &a, const vgui::Vertex_t &b );
+ virtual void DrawPolyLine(int *px, int *py, int numPoints);
+ virtual void DrawTexturedPolyLine( const vgui::Vertex_t *p, int n );
+
+ virtual void DrawFilledRect(int x0, int y0, int x1, int y1);
+ virtual void DrawFilledRectArray( IntRect *pRects, int numRects );
+ virtual void DrawFilledRectFastFade( int x0, int y0, int x1, int y1, int fadeStartPt, int fadeEndPt, unsigned int alpha0, unsigned int alpha1, bool bHorizontal );
+ virtual void DrawFilledRectFade( int x0, int y0, int x1, int y1, unsigned int alpha0, unsigned int alpha1, bool bHorizontal );
+ virtual void DrawOutlinedRect(int x0, int y0, int x1, int y1);
+ virtual void DrawOutlinedCircle(int x, int y, int radius, int segments);
+
+ // textured rendering functions
+ virtual int CreateNewTextureID( bool procedural = false );
+ virtual bool IsTextureIDValid(int id);
+
+ virtual bool DrawGetTextureFile(int id, char *filename, int maxlen );
+ virtual int DrawGetTextureId( char const *filename );
+ virtual int DrawGetTextureId( ITexture *pTexture );
+ virtual void DrawSetTextureFile(int id, const char *filename, int hardwareFilter, bool forceReload);
+ virtual void DrawSetTexture(int id);
+ virtual void DrawGetTextureSize(int id, int &wide, int &tall);
+ virtual bool DeleteTextureByID(int id);
+
+ virtual IVguiMatInfo *DrawGetTextureMatInfoFactory(int id);
+
+ virtual void DrawSetTextureRGBA(int id, const unsigned char *rgba, int wide, int tall, int hardwareFilter, bool forceReload);
+
+ virtual void DrawTexturedRect(int x0, int y0, int x1, int y1);
+ virtual void DrawTexturedSubRect( int x0, int y0, int x1, int y1, float texs0, float text0, float texs1, float text1 );
+
+ virtual void DrawTexturedPolygon(int n, vgui::Vertex_t *pVertices, bool bClipVertices = true );
+
+ virtual void DrawPrintText(const wchar_t *text, int textLen, FontDrawType_t drawType = FONT_DRAW_DEFAULT);
+ virtual void DrawUnicodeChar(wchar_t wch, FontDrawType_t drawType = FONT_DRAW_DEFAULT );
+ virtual void DrawUnicodeString( const wchar_t *pwString, FontDrawType_t drawType = FONT_DRAW_DEFAULT );
+ virtual void DrawSetTextFont(vgui::HFont font);
+ virtual void DrawFlushText();
+
+ virtual void DrawSetTextColor(int r, int g, int b, int a);
+ virtual void DrawSetTextColor(Color col);
+ virtual void DrawSetTextScale(float sx, float sy);
+ virtual void DrawSetTextPos(int x, int y);
+ virtual void DrawGetTextPos(int& x,int& y);
+
+ virtual vgui::IHTML *CreateHTMLWindow(vgui::IHTMLEvents *events,vgui::VPANEL context);
+ virtual void PaintHTMLWindow(vgui::IHTML *htmlwin);
+ virtual void DeleteHTMLWindow(vgui::IHTML *htmlwin);
+ virtual bool BHTMLWindowNeedsPaint(IHTML *htmlwin);
+
+ virtual void GetScreenSize(int &wide, int &tall);
+ virtual void SetAsTopMost(vgui::VPANEL panel, bool state);
+ virtual void BringToFront(vgui::VPANEL panel);
+ virtual void SetForegroundWindow (vgui::VPANEL panel);
+ virtual void SetPanelVisible(vgui::VPANEL panel, bool state);
+ virtual void SetMinimized(vgui::VPANEL panel, bool state);
+ virtual void FlashWindow(vgui::VPANEL panel, bool state);
+ virtual void SetTitle(vgui::VPANEL panel, const wchar_t *title);
+ virtual const wchar_t *GetTitle( vgui::VPANEL panel );
+
+ virtual void SetAsToolBar(vgui::VPANEL panel, bool state); // removes the window's task bar entry (for context menu's, etc.)
+
+ // windows stuff
+ virtual void CreatePopup(VPANEL panel, bool minimized, bool showTaskbarIcon = true, bool disabled = false, bool mouseInput = true , bool kbInput = true);
+
+ virtual void SwapBuffers(vgui::VPANEL panel);
+ virtual void Invalidate(vgui::VPANEL panel);
+
+ virtual void SetCursor(vgui::HCursor cursor);
+ virtual bool IsCursorVisible();
+ virtual void SetCursorAlwaysVisible(bool visible);
+
+ virtual void ApplyChanges();
+ virtual bool IsWithin(int x, int y);
+ virtual bool HasFocus();
+
+ virtual bool SupportsFeature(SurfaceFeature_e feature);
+
+ // engine-only focus handling (replacing WM_FOCUS windows handling)
+ virtual void SetTopLevelFocus(vgui::VPANEL panel);
+
+ // fonts
+ virtual vgui::HFont CreateFont();
+ virtual bool SetFontGlyphSet(vgui::HFont font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin = 0, int nRangeMax = 0);
+ virtual bool SetBitmapFontGlyphSet(vgui::HFont font, const char *windowsFontName, float scalex, float scaley, int flags);
+ virtual int GetFontTall(HFont font);
+ virtual int GetFontTallRequested(HFont font);
+ virtual int GetFontAscent(HFont font, wchar_t wch);
+ virtual bool IsFontAdditive(HFont font);
+ virtual void GetCharABCwide(HFont font, int ch, int &a, int &b, int &c);
+ virtual void GetTextSize(HFont font, const wchar_t *text, int &wide, int &tall);
+ virtual int GetCharacterWidth(vgui::HFont font, int ch);
+ virtual bool AddCustomFontFile(const char *fontName, const char *fontFileName);
+ virtual bool AddBitmapFontFile(const char *fontFileName);
+ virtual void SetBitmapFontName( const char *pName, const char *pFontFilename );
+ virtual const char *GetBitmapFontName( const char *pName );
+ virtual void PrecacheFontCharacters(HFont font, const wchar_t *pCharacters);
+ virtual void ClearTemporaryFontCache( void );
+ virtual const char *GetFontName( HFont font );
+ virtual const char *GetFontFamilyName( HFont font );
+
+ // GameUI-only accessed functions
+ // uploads a part of a texture, used for font rendering
+ void DrawSetSubTextureRGBA(int textureID, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall);
+ void DrawUpdateRegionTextureRGBA( int nTextureID, int x, int y, const unsigned char *pchData, int wide, int tall, ImageFormat imageFormat );
+
+ // notify icons?!?
+ virtual vgui::VPANEL GetNotifyPanel();
+ virtual void SetNotifyIcon(vgui::VPANEL context, vgui::HTexture icon, vgui::VPANEL panelToReceiveMessages, const char *text);
+
+ // plays a sound
+ virtual void PlaySound(const char *fileName);
+
+ //!! these functions Should not be accessed directly, but only through other vgui items
+ //!! need to move these to seperate interface
+ virtual int GetPopupCount();
+ virtual vgui::VPANEL GetPopup( int index );
+ virtual bool ShouldPaintChildPanel(vgui::VPANEL childPanel);
+ virtual bool RecreateContext(vgui::VPANEL panel);
+ virtual void AddPanel(vgui::VPANEL panel);
+ virtual void ReleasePanel(vgui::VPANEL panel);
+ virtual void MovePopupToFront(vgui::VPANEL panel);
+
+ virtual void SolveTraverse(vgui::VPANEL panel, bool forceApplySchemeSettings);
+ virtual void PaintTraverse(vgui::VPANEL panel);
+
+ virtual void EnableMouseCapture(vgui::VPANEL panel, bool state);
+
+ virtual void SetWorkspaceInsets( int left, int top, int right, int bottom );
+ virtual void GetWorkspaceBounds(int &x, int &y, int &wide, int &tall);
+
+ // Hook needed to Get input to work
+ virtual void AttachToWindow( void *hwnd, bool bLetAppDriveInput );
+ virtual bool HandleInputEvent( const InputEvent_t &event );
+
+ void InitFullScreenBuffer( const char *pszRenderTargetName );
+ virtual void Set3DPaintTempRenderTarget( const char *pRenderTargetName );
+ virtual void Reset3DPaintTempRenderTarget( void );
+
+ // Begins, ends 3D painting
+ virtual void Begin3DPaint( int iLeft, int iTop, int iRight, int iBottom, bool bRenderToTexture = true );
+ virtual void End3DPaint();
+
+ virtual void BeginSkinCompositionPainting() OVERRIDE;
+ virtual void EndSkinCompositionPainting() OVERRIDE;
+
+ // Disable clipping during rendering
+ virtual void DisableClipping( bool bDisable ) OVERRIDE;
+ virtual void GetClippingRect( int &left, int &top, int &right, int &bottom, bool &bClippingDisabled ) OVERRIDE;
+ virtual void SetClippingRect( int left, int top, int right, int bottom ) OVERRIDE;
+
+ // Prevents vgui from changing the cursor
+ virtual bool IsCursorLocked() const;
+
+ // Sets the mouse Get + Set callbacks
+ virtual void SetMouseCallbacks( GetMouseCallback_t GetFunc, SetMouseCallback_t SetFunc );
+
+ // Tells the surface to ignore windows messages
+ virtual void EnableWindowsMessages( bool bEnable );
+
+ // Installs a function to play sounds
+ virtual void InstallPlaySoundFunc( PlaySoundFunc_t soundFunc );
+
+ // Some drawing methods that cannot be accomplished under Win32
+ virtual void DrawColoredCircle( int centerx, int centery, float radius, int r, int g, int b, int a );
+ virtual int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, PRINTF_FORMAT_STRING const char *fmt, ... );
+ virtual void DrawColoredTextRect( vgui::HFont font, int x, int y, int w, int h, int r, int g, int b, int a, PRINTF_FORMAT_STRING const char *fmt, ... );
+ virtual void DrawTextHeight( vgui::HFont font, int w, int& h, PRINTF_FORMAT_STRING const char *fmt, ... );
+
+ // Returns the length in pixels of the text
+ virtual int DrawTextLen( vgui::HFont font, PRINTF_FORMAT_STRING const char *fmt, ... );
+
+ // Draws a panel in 3D space.
+ virtual void DrawPanelIn3DSpace( vgui::VPANEL pRootPanel, const VMatrix &panelCenterToWorld, int pw, int ph, float sw, float sh );
+
+ // Only visible within vguimatsurface
+ void DrawSetTextureMaterial(int id, IMaterial *pMaterial);
+ void ReferenceProceduralMaterial( int id, int referenceId, IMaterial *pMaterial );
+
+ // new stuff for Alfreds VGUI2 port!!
+ virtual bool InEngine() { return true; }
+ void GetProportionalBase( int &width, int &height ) { width = BASE_WIDTH; height = BASE_HEIGHT; }
+ virtual bool HasCursorPosFunctions() { return true; }
+
+ virtual void SetModalPanel(VPANEL );
+ virtual VPANEL GetModalPanel();
+ virtual void UnlockCursor();
+ virtual void LockCursor();
+ virtual void SetTranslateExtendedKeys(bool state);
+ virtual VPANEL GetTopmostPopup();
+ virtual void GetAbsoluteWindowBounds(int &x, int &y, int &wide, int &tall);
+ virtual void CalculateMouseVisible();
+ virtual bool NeedKBInput();
+ virtual void SurfaceGetCursorPos(int &x, int &y);
+ virtual void SurfaceSetCursorPos(int x, int y);
+ virtual void MovePopupToBack(VPANEL panel);
+
+ virtual bool IsInThink( VPANEL panel);
+
+ virtual bool DrawGetUnicodeCharRenderInfo( wchar_t ch, CharRenderInfo& info );
+ virtual void DrawRenderCharFromInfo( const CharRenderInfo& info );
+
+ // global alpha setting functions
+ // affect all subsequent draw calls - shouldn't normally be used directly, only in Panel::PaintTraverse()
+ virtual void DrawSetAlphaMultiplier( float alpha /* [0..1] */ );
+ virtual float DrawGetAlphaMultiplier();
+
+ // web browser
+ virtual void SetAllowHTMLJavaScript( bool state );
+
+ // video mode changing
+ virtual void OnScreenSizeChanged( int nOldWidth, int nOldHeight );
+
+ virtual vgui::HCursor CreateCursorFromFile( char const *curOrAniFile, char const *pPathID );
+
+ virtual void PaintTraverseEx(VPANEL panel, bool paintPopups = false );
+
+ virtual float GetZPos() const;
+
+ virtual void SetPanelForInput( VPANEL vpanel );
+
+ virtual vgui::IImage *GetIconImageForFullPath( char const *pFullPath );
+
+ virtual void DestroyTextureID( int id );
+
+
+ virtual const char *GetResolutionKey( void ) const;
+
+ virtual bool ForceScreenSizeOverride( bool bState, int wide, int tall );
+ // LocalToScreen, ParentLocalToScreen fixups for explicit PaintTraverse calls on Panels not at 0, 0 position
+ virtual bool ForceScreenPosOffset( bool bState, int x, int y );
+
+ virtual void OffsetAbsPos( int &x, int &y );
+
+ virtual void GetKernedCharWidth( HFont font, wchar_t ch, wchar_t chBefore, wchar_t chAfter, float &wide, float &flabcA );
+
+
+ virtual const char *GetWebkitHTMLUserAgentString() { return "Valve Client"; }
+
+ virtual void *Deprecated_AccessChromeHTMLController() { return NULL; }
+
+ virtual void SetFullscreenViewport( int x, int y, int w, int h ) OVERRIDE;
+ virtual void SetFullscreenViewportAndRenderTarget( int x, int y, int w, int h, ITexture *pRenderTarget ) OVERRIDE;
+ virtual void GetFullscreenViewportAndRenderTarget( int & x, int & y, int & w, int & h, ITexture **ppRenderTarget ) OVERRIDE;
+ virtual void GetFullscreenViewport( int & x, int & y, int & w, int & h ) OVERRIDE;
+ virtual void PushFullscreenViewport() OVERRIDE;
+ virtual void PopFullscreenViewport() OVERRIDE;
+
+ // support for software cursors
+ virtual void SetSoftwareCursor( bool bUseSoftwareCursor ) OVERRIDE;
+ virtual void PaintSoftwareCursor() OVERRIDE;
+
+ // Methods of ILocalizeTextQuery
+public:
+ //virtual int ComputeTextWidth( const wchar_t *pString );
+
+ // Causes fonts to get reloaded, etc.
+ virtual void ResetFontCaches();
+
+ virtual bool IsScreenSizeOverrideActive( void );
+ virtual bool IsScreenPosOverrideActive( void );
+
+ virtual IMaterial *DrawGetTextureMaterial( int id );
+
+ virtual int GetTextureNumFrames( int id );
+ virtual void DrawSetTextureFrame( int id, int nFrame, unsigned int *pFrameCache );
+
+private:
+ //void DrawRenderCharInternal( const FontCharRenderInfo& info );
+ void DrawRenderCharInternal( const CharRenderInfo& info );
+
+private:
+ enum { BASE_HEIGHT = 480, BASE_WIDTH = 640 };
+
+ struct PaintState_t
+ {
+ vgui::VPANEL m_pPanel;
+ int m_iTranslateX;
+ int m_iTranslateY;
+ int m_iScissorLeft;
+ int m_iScissorRight;
+ int m_iScissorTop;
+ int m_iScissorBottom;
+ };
+
+ // material Setting method
+ void InternalSetMaterial( IMaterial *material = NULL );
+
+ // Draws the fullscreen buffer into the panel
+ void DrawFullScreenBuffer( int nLeft, int nTop, int nRight, int nBottom );
+
+ // Helper method to initialize vertices (transforms them into screen space too)
+ void InitVertex( vgui::Vertex_t &vertex, int x, int y, float u, float v );
+
+ // Draws a quad + quad array
+ void DrawQuad( const vgui::Vertex_t &ul, const vgui::Vertex_t &lr, unsigned char *pColor );
+ void DrawQuadArray( int numQuads, vgui::Vertex_t *pVerts, unsigned char *pColor, bool bShouldClip = true );
+
+ // Necessary to wrap the rendering
+ void StartDrawing( void );
+ void StartDrawingIn3DSpace( const VMatrix &screenToWorld, int pw, int ph, float sw, float sh );
+ void FinishDrawing( void );
+
+ // Sets up a particular painting state...
+ void SetupPaintState( const PaintState_t &paintState );
+
+ void ResetPopupList();
+ void AddPopup( vgui::VPANEL panel );
+ void RemovePopup( vgui::VPANEL panel );
+ void AddPopupsToList( vgui::VPANEL panel );
+
+ // Helper for drawing colored text
+ int DrawColoredText( vgui::HFont font, int x, int y, int r, int g, int b, int a, const char *fmt, va_list argptr );
+ void SearchForWordBreak( vgui::HFont font, char *text, int& chars, int& pixels );
+
+ void InternalThinkTraverse(VPANEL panel);
+ void InternalSolveTraverse(VPANEL panel);
+ void InternalSchemeSettingsTraverse(VPANEL panel, bool forceApplySchemeSettings);
+
+ // handles mouse movement
+ void SetCursorPos(int x, int y);
+ void GetCursorPos(int &x, int &y);
+
+ void DrawTexturedLineInternal( const Vertex_t &a, const Vertex_t &b );
+
+ // Gets texture coordinates for drawing the full screen buffer
+ void GetFullScreenTexCoords( int x, int y, int w, int h, float *pMinU, float *pMinV, float *pMaxU, float *pMaxV );
+
+ // Is a panel under the restricted panel?
+ bool IsPanelUnderRestrictedPanel( VPANEL panel );
+
+ // Point Translation for current panel
+ int m_nTranslateX;
+ int m_nTranslateY;
+
+ // alpha multiplier for current panel [0..1]
+ float m_flAlphaMultiplier;
+
+ // The size of the window to draw into
+ int m_pSurfaceExtents[4];
+
+ // Color for drawing all non-text things
+ unsigned char m_DrawColor[4];
+
+ // Color for drawing text
+ unsigned char m_DrawTextColor[4];
+
+ // Location of text rendering
+ int m_pDrawTextPos[2];
+
+ // Meshbuilder used for drawing
+ IMesh* m_pMesh;
+ CMeshBuilder meshBuilder;
+
+ // White material used for drawing non-textured things
+ CMaterialReference m_pWhite;
+
+ // Used for 3D-rendered images
+ CTextureReference m_FullScreenBuffer;
+ CMaterialReference m_FullScreenBufferMaterial;
+ int m_nFullScreenBufferMaterialId;
+ CUtlString m_FullScreenBufferName;
+
+ bool m_bUsingTempFullScreenBufferMaterial;
+
+ // Root panel
+ vgui::VPANEL m_pEmbeddedPanel;
+ vgui::Panel *m_pDefaultEmbeddedPanel;
+ vgui::VPANEL m_pRestrictedPanel;
+
+ // List of pop-up panels based on the type enum above (draw order vs last clicked)
+ CUtlVector<vgui::HPanel> m_PopupList;
+
+ // Stack of paint state...
+ CUtlVector< PaintState_t > m_PaintStateStack;
+
+ vgui::HFont m_hCurrentFont;
+ vgui::HCursor _currentCursor;
+ bool m_cursorAlwaysVisible;
+
+ // The currently bound texture
+ int m_iBoundTexture;
+
+ // font drawing batching code
+ enum { MAX_BATCHED_CHAR_VERTS = 4096 };
+ vgui::Vertex_t m_BatchedCharVerts[ MAX_BATCHED_CHAR_VERTS ];
+ int m_nBatchedCharVertCount;
+
+ // What's the rectangle we're drawing in 3D paint mode?
+ int m_n3DLeft, m_n3DRight, m_n3DTop, m_n3DBottom;
+
+ // Are we painting in 3D? (namely drawing 3D objects *inside* the vgui panel)
+ bool m_bIn3DPaintMode : 1;
+
+ // If we are in 3d Paint mode, are we rendering to a texture? (Or directly to the screen)
+ bool m_b3DPaintRenderToTexture : 1;
+
+ // Are we drawing the vgui panel in the 3D world somewhere?
+ bool m_bDrawingIn3DWorld : 1;
+
+ // Is the app gonna call HandleInputEvent?
+ bool m_bAppDrivesInput : 1;
+
+ // Are we currently in the think() loop
+ bool m_bInThink : 1;
+
+ bool m_bNeedsKeyboard : 1;
+ bool m_bNeedsMouse : 1;
+ bool m_bAllowJavaScript : 1;
+
+ int m_nLastInputPollCount;
+
+ VPANEL m_CurrentThinkPanel;
+
+ // The attached HWND
+ void *m_HWnd;
+
+ // Installed function to play sounds
+ PlaySoundFunc_t m_PlaySoundFunc;
+
+ int m_WorkSpaceInsets[4];
+
+ class TitleEntry
+ {
+ public:
+ TitleEntry()
+ {
+ panel = NULL;
+ title[0] = 0;
+ }
+
+ vgui::VPANEL panel;
+ wchar_t title[128];
+ };
+
+ CUtlVector< TitleEntry > m_Titles;
+ CUtlVector< CUtlSymbol > m_CustomFontFileNames;
+ CUtlVector< CUtlSymbol > m_BitmapFontFileNames;
+ CUtlDict< int, int > m_BitmapFontFileMapping;
+
+ float m_flZPos;
+ CUtlDict< vgui::IImage *, unsigned short > m_FileTypeImages;
+
+ int GetTitleEntry( vgui::VPANEL panel );
+
+ virtual void DrawSetTextureRGBAEx(int id, const unsigned char *rgba, int wide, int tall, ImageFormat format );
+
+ struct ScreenOverride_t
+ {
+ ScreenOverride_t() : m_bActive( false )
+ {
+ m_nValue[ 0 ] = m_nValue[ 1 ] = 0;
+ }
+ bool m_bActive;
+ int m_nValue[ 2 ];
+ };
+
+ ScreenOverride_t m_ScreenSizeOverride;
+ ScreenOverride_t m_ScreenPosOverride;
+
+ int m_nFullscreenViewportX;
+ int m_nFullscreenViewportY;
+ int m_nFullscreenViewportWidth;
+ int m_nFullscreenViewportHeight;
+ ITexture *m_pFullscreenRenderTarget;
+
+#ifdef LINUX
+ struct font_entry
+ {
+ void *data;
+ int size;
+ };
+
+ static CUtlDict< font_entry, unsigned short > m_FontData;
+
+ static void *FontDataHelper( const char *pchFontName, int &size, const char *fontFileName );
+#endif
+};
+
+#if GLMDEBUG
+class MatSurfFuncLogger // rip off of GLMFuncLogger - figure out a way to reunify these soon
+{
+ public:
+
+ // simple function log
+ MatSurfFuncLogger( char *funcName )
+ {
+ CMatRenderContextPtr prc( g_pMaterialSystem );
+
+ m_funcName = funcName;
+ m_earlyOut = false;
+
+ prc->Printf( ">%s", m_funcName );
+ };
+
+ // more advanced version lets you pass args (i.e. called parameters or anything else of interest)
+ // no macro for this one, since no easy way to pass through the args as well as the funcname
+ MatSurfFuncLogger( char *funcName, PRINTF_FORMAT_STRING const char *fmt, ... )
+ {
+ CMatRenderContextPtr prc( g_pMaterialSystem );
+
+ m_funcName = funcName;
+ m_earlyOut = false;
+
+ // this acts like GLMPrintf here
+ // all the indent policy is down in GLMPrintfVA
+ // which means we need to inject a ">" at the front of the format string to make this work... sigh.
+
+ char modifiedFmt[2000];
+ modifiedFmt[0] = '>';
+ strcpy( modifiedFmt+1, fmt );
+
+ va_list vargs;
+ va_start(vargs, fmt);
+ prc->PrintfVA( modifiedFmt, vargs );
+ va_end( vargs );
+ }
+
+ ~MatSurfFuncLogger( )
+ {
+ CMatRenderContextPtr prc( g_pMaterialSystem );
+ if (m_earlyOut)
+ {
+ prc->Printf( "<%s (early out)", m_funcName );
+ }
+ else
+ {
+ prc->Printf( "<%s", m_funcName );
+ }
+ };
+
+ void EarlyOut( void )
+ {
+ m_earlyOut = true;
+ };
+
+
+ char *m_funcName; // set at construction time
+ bool m_earlyOut;
+};
+
+// handy macro to go with the helper class
+#define MAT_FUNC MatSurfFuncLogger _logger_ ( __FUNCTION__ )
+
+#else
+
+#define MAT_FUNC
+
+#endif
+
+#endif // MATSYSTEMSURFACE_H
diff --git a/vguimatsurface/TextureDictionary.cpp b/vguimatsurface/TextureDictionary.cpp
new file mode 100644
index 0000000..d8fe072
--- /dev/null
+++ b/vguimatsurface/TextureDictionary.cpp
@@ -0,0 +1,991 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains all texture state for the material system surface to use
+//
+//===========================================================================//
+
+#include "bitmap/imageformat.h"
+#include "TextureDictionary.h"
+#include "utllinkedlist.h"
+#include "checksum_crc.h"
+#include "materialsystem/imaterial.h"
+#include "vguimatsurface.h"
+#include "materialsystem/imaterialsystem.h"
+#include "tier0/dbg.h"
+#include "KeyValues.h"
+#include "pixelwriter.h"
+#include "materialsystem/imaterialvar.h"
+#include "materialsystem/itexture.h"
+#include "vtf/vtf.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+#define TEXTURE_ID_UNKNOWN -1
+
+class CMatSystemTexture;
+
+// Case-sensitive string checksum
+static CRC32_t Texture_CRCName( const char *string )
+{
+ CRC32_t crc;
+
+ CRC32_Init( &crc );
+ CRC32_ProcessBuffer( &crc, (void *)string, strlen( string ) );
+ CRC32_Final( &crc );
+
+ return crc;
+}
+
+class CFontTextureRegen;
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+class CMatSystemTexture
+{
+public:
+ CMatSystemTexture( void );
+ ~CMatSystemTexture( void );
+
+ void SetId( int id ) { m_ID = id; };
+
+ CRC32_t GetCRC() const;
+ void SetCRC( CRC32_t val );
+
+ void SetMaterial( const char *pFileName );
+ void SetMaterial( IMaterial *pMaterial );
+
+ void SetTexture( ITexture *pTexture ) { SafeAssign( &m_pOverrideTexture, pTexture ); }
+
+ // This is used when we want different rendering state sharing the same procedural texture (fonts)
+ void ReferenceOtherProcedural( CMatSystemTexture *pTexture, IMaterial *pMaterial );
+
+ IMaterial *GetMaterial() { return m_pMaterial; }
+ int Width() const { return m_iWide; }
+ int Height() const { return m_iTall; }
+
+ bool IsProcedural( void ) const;
+ void SetProcedural( bool proc );
+
+ bool IsReference() const { return m_Flags & TEXTURE_IS_REFERENCE; }
+
+ void SetTextureRGBA( const char* rgba, int wide, int tall, ImageFormat format, bool bFixupTextCoordsForDimensions );
+ void SetSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall );
+ void SetSubTextureRGBAEx( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
+ void UpdateSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
+
+ float m_s0, m_t0, m_s1, m_t1;
+
+private:
+ void CreateRegen( int nWidth, int nHeight, ImageFormat format );
+ void ReleaseRegen( void );
+ void CleanUpMaterial();
+
+ ITexture *GetTextureValue( void );
+
+private:
+ enum
+ {
+ TEXTURE_IS_PROCEDURAL = 0x1,
+ TEXTURE_IS_REFERENCE = 0x2
+ };
+
+ CRC32_t m_crcFile;
+ IMaterial *m_pMaterial;
+ ITexture *m_pTexture;
+ ITexture *m_pOverrideTexture;
+
+ int m_iWide;
+ int m_iTall;
+ int m_iInputWide;
+ int m_iInputTall;
+ int m_ID;
+ int m_Flags;
+ CFontTextureRegen *m_pRegen;
+};
+
+
+//-----------------------------------------------------------------------------
+// A class that manages textures used by the material system surface
+//-----------------------------------------------------------------------------
+class CTextureDictionary : public ITextureDictionary
+{
+public:
+ CTextureDictionary( void );
+
+ // Create, destroy textures
+ int CreateTexture( bool procedural = false );
+ int CreateTextureByTexture( ITexture *pTexture, bool procedural = true ) OVERRIDE;
+ void DestroyTexture( int id );
+ void DestroyAllTextures();
+
+ // Is this a valid id?
+ bool IsValidId( int id ) const;
+
+ // Binds a material to a texture
+ virtual void BindTextureToFile( int id, const char *pFileName );
+ virtual void BindTextureToMaterial( int id, IMaterial *pMaterial );
+ virtual void BindTextureToMaterialReference( int id, int referenceId, IMaterial *pMaterial );
+
+ // Texture info
+ IMaterial *GetTextureMaterial( int id );
+ void GetTextureSize(int id, int& iWide, int& iTall );
+ void GetTextureTexCoords( int id, float &s0, float &t0, float &s1, float &t1 );
+
+ void SetTextureRGBA( int id, const char* rgba, int wide, int tall );
+ void SetTextureRGBAEx( int id, const char* rgba, int wide, int tall, ImageFormat format, bool bFixupTextCoordsForDimensions );
+ void SetSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall );
+ void SetSubTextureRGBAEx( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
+ void UpdateSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat );
+
+ int FindTextureIdForTextureFile( char const *pFileName );
+
+public:
+ CMatSystemTexture *GetTexture( int id );
+
+private:
+ CUtlLinkedList< CMatSystemTexture, unsigned short > m_Textures;
+};
+
+static CTextureDictionary s_TextureDictionary;
+
+
+//-----------------------------------------------------------------------------
+// A texture regenerator that holds onto the bits at all times
+//-----------------------------------------------------------------------------
+class CFontTextureRegen : public ITextureRegenerator
+{
+public:
+ CFontTextureRegen( int nWidth, int nHeight, ImageFormat format )
+ {
+ m_nFormat = format;
+ m_nWidth = nWidth;
+ m_nHeight = nHeight;
+
+ if ( IsPC() )
+ {
+ int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
+ m_pTextureBits = new unsigned char[size];
+ memset( m_pTextureBits, 0, size );
+ }
+ else
+ {
+ // will be allocated as needed
+ m_pTextureBits = NULL;
+ }
+ }
+
+ ~CFontTextureRegen( void )
+ {
+ DeleteTextureBits();
+ }
+
+ void UpdateBackingBits( Rect_t &subRect, const unsigned char *pBits, Rect_t &uploadRect, ImageFormat format )
+ {
+ int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
+ if ( IsPC() )
+ {
+ if ( !m_pTextureBits )
+ return;
+ }
+ else
+ {
+ Assert( !m_pTextureBits );
+ m_pTextureBits = new unsigned char[size];
+ memset( m_pTextureBits, 0, size );
+ }
+
+ // Copy subrect into backing bits storage
+ // source data is expected to be in same format as backing bits
+ int y;
+ if ( ImageLoader::SizeInBytes( m_nFormat ) == 4 )
+ {
+ bool bIsInputFullRect = ( subRect.width != uploadRect.width || subRect.height != uploadRect.height );
+ Assert( (subRect.x >= 0) && (subRect.y >= 0) );
+ Assert( (subRect.x + subRect.width <= m_nWidth) && (subRect.y + subRect.height <= m_nHeight) );
+ for ( y=0; y < subRect.height; ++y )
+ {
+ int idx = ( (subRect.y + y) * m_nWidth + subRect.x ) << 2;
+ unsigned int *pDst = (unsigned int*)(&m_pTextureBits[ idx ]);
+ int offset = bIsInputFullRect ? (subRect.y+y)*uploadRect.width + subRect.x : y*uploadRect.width;
+ const unsigned int *pSrc = (const unsigned int *)(&pBits[ offset << 2 ]);
+ ImageLoader::ConvertImageFormat( (const unsigned char *)pSrc, format,(unsigned char *)pDst, m_nFormat, subRect.width, 1 );
+ }
+ }
+ else
+ {
+ // cannot subrect copy when format is not RGBA
+ if ( subRect.width != m_nWidth || subRect.height != m_nHeight )
+ {
+ Assert( 0 );
+ return;
+ }
+ Q_memcpy( m_pTextureBits, pBits, size );
+ }
+ }
+
+ virtual void RegenerateTextureBits( ITexture *pTexture, IVTFTexture *pVTFTexture, Rect_t *pSubRect )
+ {
+ if ( !m_pTextureBits )
+ return;
+
+ Assert( (pVTFTexture->Width() == m_nWidth) && (pVTFTexture->Height() == m_nHeight) );
+
+ int nFormatBytes = ImageLoader::SizeInBytes( m_nFormat );
+ if ( nFormatBytes == 4 )
+ {
+ if ( m_nFormat == pVTFTexture->Format() )
+ {
+ int ymax = pSubRect->y + pSubRect->height;
+ for( int y = pSubRect->y; y < ymax; ++y )
+ {
+ // copy each row across for the update
+ char *pchData = (char *)pVTFTexture->ImageData( 0, 0, 0, 0, y ) + pSubRect->x *nFormatBytes;
+ int size = ImageLoader::GetMemRequired( pSubRect->width, 1, 1, m_nFormat, false );
+ V_memcpy( pchData, m_pTextureBits + (y * m_nWidth + pSubRect->x) * nFormatBytes, size );
+ }
+ }
+ else
+ {
+ // formats don't match so do a pixel by pixel swizel
+ CPixelWriter pixelWriter;
+ pixelWriter.SetPixelMemory(
+ pVTFTexture->Format(),
+ pVTFTexture->ImageData( 0, 0, 0 ),
+ pVTFTexture->RowSizeInBytes( 0 ) );
+
+ // Now upload the part we've been asked for
+ int xmax = pSubRect->x + pSubRect->width;
+ int ymax = pSubRect->y + pSubRect->height;
+ int x, y;
+
+ for( y = pSubRect->y; y < ymax; ++y )
+ {
+ pixelWriter.Seek( pSubRect->x, y );
+ unsigned char *rgba = &m_pTextureBits[ (y * m_nWidth + pSubRect->x) * nFormatBytes ];
+
+ for ( x=pSubRect->x; x < xmax; ++x )
+ {
+ pixelWriter.WritePixel( rgba[0], rgba[1], rgba[2], rgba[3] );
+ rgba += nFormatBytes;
+ }
+ }
+ }
+ }
+ else
+ {
+ // cannot subrect copy when format is not RGBA
+ if ( pSubRect->width != m_nWidth || pSubRect->height != m_nHeight )
+ {
+ Assert( 0 );
+ return;
+ }
+ int size = ImageLoader::GetMemRequired( m_nWidth, m_nHeight, 1, m_nFormat, false );
+ Q_memcpy( pVTFTexture->ImageData( 0, 0, 0 ), m_pTextureBits, size );
+ }
+ }
+
+ virtual void Release()
+ {
+ // Called by the material system when this needs to go away
+ DeleteTextureBits();
+ }
+
+ void DeleteTextureBits()
+ {
+ if ( m_pTextureBits )
+ {
+ delete [] m_pTextureBits;
+ m_pTextureBits = NULL;
+ }
+ }
+
+private:
+ unsigned char *m_pTextureBits;
+ short m_nWidth;
+ short m_nHeight;
+ ImageFormat m_nFormat;
+};
+
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CMatSystemTexture::CMatSystemTexture( void )
+{
+ m_pMaterial = NULL;
+ m_pTexture = NULL;
+ m_pOverrideTexture = NULL;
+ m_crcFile = (CRC32_t)0;
+ m_iWide = m_iTall = 0;
+ m_s0 = m_t0 = 0;
+ m_s1 = m_t1 = 1;
+
+ m_Flags = 0;
+ m_pRegen = NULL;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+CMatSystemTexture::~CMatSystemTexture( void )
+{
+ if ( m_pOverrideTexture )
+ {
+ m_pOverrideTexture->Release();
+ m_pOverrideTexture->DeleteIfUnreferenced();
+ m_pOverrideTexture = NULL;
+ }
+
+ CleanUpMaterial();
+}
+
+bool CMatSystemTexture::IsProcedural( void ) const
+{
+ return (m_Flags & TEXTURE_IS_PROCEDURAL) != 0;
+}
+
+void CMatSystemTexture::SetProcedural( bool proc )
+{
+ if (proc)
+ {
+ m_Flags |= TEXTURE_IS_PROCEDURAL;
+ }
+ else
+ {
+ m_Flags &= ~TEXTURE_IS_PROCEDURAL;
+ }
+}
+
+void CMatSystemTexture::CleanUpMaterial()
+{
+ if ( m_pMaterial )
+ {
+ // causes the underlying texture (if unreferenced) to be deleted as well
+ m_pMaterial->DecrementReferenceCount();
+ m_pMaterial->DeleteIfUnreferenced();
+ m_pMaterial = NULL;
+ }
+
+ if ( m_pTexture )
+ {
+ m_pTexture->SetTextureRegenerator( NULL );
+ m_pTexture->DecrementReferenceCount();
+ m_pTexture->DeleteIfUnreferenced();
+ m_pTexture = NULL;
+ }
+
+ ReleaseRegen();
+}
+
+void CMatSystemTexture::CreateRegen( int nWidth, int nHeight, ImageFormat format )
+{
+ Assert( IsProcedural() );
+
+ if ( !m_pRegen )
+ {
+ m_pRegen = new CFontTextureRegen( nWidth, nHeight, format );
+ }
+}
+
+void CMatSystemTexture::ReleaseRegen( void )
+{
+ if (m_pRegen)
+ {
+ if (!IsReference())
+ {
+ delete m_pRegen;
+ }
+
+ m_pRegen = NULL;
+ }
+}
+
+void CMatSystemTexture::SetTextureRGBA( const char *rgba, int wide, int tall, ImageFormat format, bool bFixupTextCoords )
+{
+ Assert( IsProcedural() );
+ if ( !IsProcedural() )
+ return;
+
+ if ( !m_pMaterial )
+ {
+ int width = wide;
+ int height = tall;
+
+ // find the minimum power-of-two to fit this in
+ int i;
+ for ( i = 0; i < 32 ; i++ )
+ {
+ width = (1<<i);
+ if (width >= wide)
+ {
+ break;
+ }
+ }
+
+ for (i = 0; i < 32; i++ )
+ {
+ height= (1<<i);
+ if (height >= tall)
+ {
+ break;
+ }
+ }
+
+ // create a procedural material to fit this texture into
+ static int nTextureId = 0;
+ char pTextureName[64];
+ Q_snprintf( pTextureName, sizeof( pTextureName ), "__vgui_texture_%d", nTextureId );
+ ++nTextureId;
+
+ ITexture *pTexture = g_pMaterialSystem->CreateProceduralTexture(
+ pTextureName,
+ TEXTURE_GROUP_VGUI,
+ width,
+ height,
+ format,
+ TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT |
+ TEXTUREFLAGS_NOMIP | TEXTUREFLAGS_NOLOD |
+ TEXTUREFLAGS_PROCEDURAL | TEXTUREFLAGS_SINGLECOPY | TEXTUREFLAGS_POINTSAMPLE );
+
+ KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
+ pVMTKeyValues->SetInt( "$vertexcolor", 1 );
+ pVMTKeyValues->SetInt( "$vertexalpha", 1 );
+ pVMTKeyValues->SetInt( "$ignorez", 1 );
+ pVMTKeyValues->SetInt( "$no_fullbright", 1 );
+ pVMTKeyValues->SetInt( "$translucent", 1 );
+ pVMTKeyValues->SetString( "$basetexture", pTextureName );
+
+ IMaterial *pMaterial = g_pMaterialSystem->CreateMaterial( pTextureName, pVMTKeyValues );
+ pMaterial->Refresh();
+
+ // Has to happen after the refresh
+ pTexture->DecrementReferenceCount();
+
+ SetMaterial( pMaterial );
+ m_iInputTall = tall;
+ m_iInputWide = wide;
+ if ( bFixupTextCoords && ( wide != width || tall != height ) )
+ {
+ m_s1 = (double)wide / width;
+ m_t1 = (double)tall / height;
+ }
+
+ // undo the extra +1 refCount
+ pMaterial->DecrementReferenceCount();
+ }
+
+ Assert( wide <= m_iWide );
+ Assert( tall <= m_iTall );
+
+ // Just replace the whole thing
+ SetSubTextureRGBAEx( 0, 0, (const unsigned char *)rgba, wide, tall, format );
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+//-----------------------------------------------------------------------------
+ITexture *CMatSystemTexture::GetTextureValue( void )
+{
+ Assert( IsProcedural() );
+ if ( !m_pMaterial )
+ return NULL;
+
+ if ( m_pOverrideTexture )
+ return m_pOverrideTexture;
+
+ return m_pTexture;
+}
+
+void CMatSystemTexture::SetSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
+{
+ SetSubTextureRGBAEx( drawX, drawY, rgba, subTextureWide, subTextureTall, IMAGE_FORMAT_RGBA8888 );
+}
+
+void CMatSystemTexture::SetSubTextureRGBAEx( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat format )
+{
+ ITexture *pTexture = GetTextureValue();
+ if ( !pTexture )
+ return;
+
+ Assert( IsProcedural() );
+ if ( !IsProcedural() )
+ return;
+
+ Assert( drawX < m_iWide );
+ Assert( drawY < m_iTall );
+ Assert( drawX + subTextureWide <= m_iWide );
+ Assert( drawY + subTextureTall <= m_iTall );
+
+ Assert( m_pRegen );
+
+ Assert( rgba );
+
+ Rect_t subRect;
+ subRect.x = drawX;
+ subRect.y = drawY;
+ subRect.width = subTextureWide;
+ subRect.height = subTextureTall;
+
+ Rect_t textureSize;
+ textureSize.x = 0;
+ textureSize.y = 0;
+ textureSize.width = subTextureWide;
+ textureSize.height = subTextureTall;
+
+
+ m_pRegen->UpdateBackingBits( subRect, rgba, textureSize, format );
+ pTexture->Download( &subRect );
+
+ if ( IsX360() )
+ {
+ // xboxissue - no need to persist "backing bits", saves memory
+ // the texture (commonly font page) "backing bits" are allocated during UpdateBackingBits() which get blitted
+ // into by procedural regeneration in preparation for download() which then subrect blits
+ // out of and into target texture (d3d upload)
+ // the "backing bits" are then no longer required
+ m_pRegen->DeleteTextureBits();
+ }
+}
+
+void CMatSystemTexture::UpdateSubTextureRGBA( int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat )
+{
+ ITexture *pTexture = GetTextureValue();
+ if ( !pTexture )
+ return;
+
+ Assert( IsProcedural() );
+ if ( !IsProcedural() )
+ return;
+
+ Assert( drawX < m_iWide );
+ Assert( drawY < m_iTall );
+ Assert( drawX + subTextureWide <= m_iWide );
+ Assert( drawY + subTextureTall <= m_iTall );
+
+ Assert( m_pRegen );
+
+ Assert( rgba );
+
+ Rect_t subRect;
+ subRect.x = drawX;
+ subRect.y = drawY;
+ subRect.width = subTextureWide;
+ subRect.height = subTextureTall;
+
+ Rect_t textureSize;
+ textureSize.x = 0;
+ textureSize.y = 0;
+ textureSize.width = m_iInputWide;
+ textureSize.height = m_iInputTall;
+
+ m_pRegen->UpdateBackingBits( subRect, rgba, textureSize, imageFormat );
+ pTexture->Download( &subRect );
+
+ if ( IsX360() )
+ {
+ // xboxissue - no need to persist "backing bits", saves memory
+ // the texture (commonly font page) "backing bits" are allocated during UpdateBackingBits() which get blitted
+ // into by procedural regeneration in preparation for download() which then subrect blits
+ // out of and into target texture (d3d upload)
+ // the "backing bits" are then no longer required
+ m_pRegen->DeleteTextureBits();
+ }
+}
+
+
+
+void CMatSystemTexture::SetCRC( CRC32_t val )
+{
+ m_crcFile = val;
+}
+
+CRC32_t CMatSystemTexture::GetCRC() const
+{
+ return m_crcFile;
+}
+
+void CMatSystemTexture::SetMaterial( IMaterial *pMaterial )
+{
+ // Decrement references to old texture
+ CleanUpMaterial();
+
+ m_pMaterial = pMaterial;
+
+ if (!m_pMaterial)
+ {
+ m_iWide = m_iTall = 0;
+ m_s0 = m_t0 = 0.0f;
+ m_s1 = m_t1 = 1.0f;
+ return;
+ }
+
+ // Increment its reference count
+ m_pMaterial->IncrementReferenceCount();
+
+ // Compute texture size
+ m_iWide = m_pMaterial->GetMappingWidth();
+ m_iTall = m_pMaterial->GetMappingHeight();
+
+ // Compute texture coordinates
+ float flPixelCenterX = 0.0f;
+ float flPixelCenterY = 0.0f;
+
+ if ( m_iWide > 0.0f && m_iTall > 0.0f)
+ {
+ flPixelCenterX = 0.5f / m_iWide;
+ flPixelCenterY = 0.5f / m_iTall;
+ }
+
+ m_s0 = flPixelCenterX;
+ m_t0 = flPixelCenterY;
+
+ // FIXME: Old code used +, it should be - yes?!??!
+ m_s1 = 1.0 - flPixelCenterX;
+ m_t1 = 1.0 - flPixelCenterY;
+
+ if ( IsProcedural() )
+ {
+ bool bFound;
+ IMaterialVar *tv = m_pMaterial->FindVar( "$baseTexture", &bFound );
+ if ( bFound && tv->IsTexture() )
+ {
+ m_pTexture = tv->GetTextureValue();
+ if ( m_pTexture )
+ {
+ m_pTexture->IncrementReferenceCount();
+
+ // Upload new data
+ CreateRegen( m_iWide, m_iTall, m_pTexture->GetImageFormat() );
+ m_pTexture->SetTextureRegenerator( m_pRegen );
+ }
+ }
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// This is used when we want different rendering state sharing the same procedural texture (fonts)
+//-----------------------------------------------------------------------------
+void CMatSystemTexture::ReferenceOtherProcedural( CMatSystemTexture *pTexture, IMaterial *pMaterial )
+{
+ // Decrement references to old texture
+ CleanUpMaterial();
+
+ Assert( pTexture->IsProcedural() );
+
+ m_Flags |= TEXTURE_IS_REFERENCE;
+
+ m_pMaterial = pMaterial;
+
+ if (!m_pMaterial)
+ {
+ m_iWide = m_iTall = 0;
+ m_s0 = m_t0 = 0.0f;
+ m_s1 = m_t1 = 1.0f;
+ return;
+ }
+
+ m_iWide = pTexture->m_iWide;
+ m_iTall = pTexture->m_iTall;
+ m_s0 = pTexture->m_s0;
+ m_t0 = pTexture->m_t0;
+ m_s1 = pTexture->m_s1;
+ m_t1 = pTexture->m_t1;
+
+ Assert( (pMaterial->GetMappingWidth() == m_iWide) && (pMaterial->GetMappingHeight() == m_iTall) );
+
+ // Increment its reference count
+ m_pMaterial->IncrementReferenceCount();
+
+ bool bFound;
+ IMaterialVar *tv = m_pMaterial->FindVar( "$baseTexture", &bFound );
+ if ( bFound )
+ {
+ m_pTexture = tv->GetTextureValue();
+ if ( m_pTexture )
+ {
+ m_pTexture->IncrementReferenceCount();
+ Assert( m_pTexture == pTexture->m_pTexture );
+
+ // Reference, but do *not* create a new one!!!
+ m_pRegen = pTexture->m_pRegen;
+ }
+ }
+}
+
+void CMatSystemTexture::SetMaterial( const char *pFileName )
+{
+ // Get a pointer to the new material
+ IMaterial *pMaterial = g_pMaterialSystem->FindMaterial( pFileName, TEXTURE_GROUP_VGUI );
+
+ if ( IsErrorMaterial( pMaterial ) )
+ {
+ if (IsOSX())
+ {
+ printf( "\n ##### Missing Vgui material %s\n", pFileName );
+ }
+ Msg( "--- Missing Vgui material %s\n", pFileName );
+ }
+
+ SetMaterial( pMaterial );
+}
+
+//-----------------------------------------------------------------------------
+// Singleton instance
+//-----------------------------------------------------------------------------
+ITextureDictionary *TextureDictionary()
+{
+ return &s_TextureDictionary;
+}
+
+CTextureDictionary::CTextureDictionary( void )
+{
+ // First entry is bogus texture
+ m_Textures.AddToTail();
+}
+
+//-----------------------------------------------------------------------------
+// Create, destroy textures
+//-----------------------------------------------------------------------------
+int CTextureDictionary::CreateTexture( bool procedural /*=false*/ )
+{
+ int idx = m_Textures.AddToTail();
+ CMatSystemTexture &texture = m_Textures[idx];
+ texture.SetProcedural( procedural );
+ texture.SetId( idx );
+
+ return idx;
+}
+
+int CTextureDictionary::CreateTextureByTexture( ITexture *pTexture, bool procedural /*= true*/ )
+{
+ int idx = m_Textures.AddToTail();
+ CMatSystemTexture &texture = m_Textures[idx];
+ texture.SetProcedural( procedural );
+ texture.SetId( idx );
+ texture.SetTexture( pTexture );
+
+ return idx;
+}
+
+void CTextureDictionary::DestroyTexture( int id )
+{
+ if ( m_Textures.Count() <= 1 )
+ {
+ // TextureDictionary already destroyed all the textures before this (something destructed late in shutdown)
+ return;
+ }
+
+ if (id != INVALID_TEXTURE_ID)
+ {
+ Assert( id != m_Textures.InvalidIndex() );
+ m_Textures.Remove( (unsigned short)id );
+ }
+}
+
+void CTextureDictionary::DestroyAllTextures()
+{
+ m_Textures.RemoveAll();
+ // First entry is bogus texture
+ m_Textures.AddToTail();
+ CMatSystemTexture &texture = m_Textures[0];
+ texture.SetId( 0 );
+}
+
+void CTextureDictionary::SetTextureRGBA( int id, const char* rgba, int wide, int tall )
+{
+ SetTextureRGBAEx( id, rgba, wide, tall, IMAGE_FORMAT_RGBA8888, false );
+}
+
+void CTextureDictionary::SetTextureRGBAEx( int id, const char* rgba, int wide, int tall, ImageFormat format, bool bFixupTextCoordsForDimensions )
+{
+ if (!IsValidId(id))
+ {
+ Msg( "SetTextureRGBA: Invalid texture id %i\n", id );
+ return;
+ }
+ CMatSystemTexture &texture = m_Textures[id];
+ texture.SetTextureRGBA( rgba, wide, tall, format, bFixupTextCoordsForDimensions );
+}
+
+void CTextureDictionary::SetSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall )
+{
+ SetSubTextureRGBAEx( id, drawX, drawY, rgba, subTextureWide, subTextureTall, IMAGE_FORMAT_RGBA8888 );
+}
+
+
+void CTextureDictionary::SetSubTextureRGBAEx( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat format )
+{
+ if (!IsValidId(id))
+ {
+ Msg( "SetSubTextureRGBA: Invalid texture id %i\n", id );
+ return;
+ }
+
+ CMatSystemTexture &texture = m_Textures[id];
+ texture.SetSubTextureRGBAEx( drawX, drawY, rgba, subTextureWide, subTextureTall, format );
+}
+
+
+void CTextureDictionary::UpdateSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat )
+{
+ if (!IsValidId(id))
+ {
+ Msg( "UpdateSubTextureRGBA: Invalid texture id %i\n", id );
+ return;
+ }
+
+ CMatSystemTexture &texture = m_Textures[id];
+ texture.UpdateSubTextureRGBA( drawX, drawY, rgba, subTextureWide, subTextureTall, imageFormat );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns true if the id is valid
+//-----------------------------------------------------------------------------
+bool CTextureDictionary::IsValidId( int id ) const
+{
+ Assert( id != 0 );
+ if ( id == 0 )
+ return false;
+
+ return m_Textures.IsValidIndex( id );
+}
+
+
+//-----------------------------------------------------------------------------
+// Binds a file to a particular texture
+//-----------------------------------------------------------------------------
+void CTextureDictionary::BindTextureToFile( int id, const char *pFileName )
+{
+ if (!IsValidId(id))
+ {
+ Msg( "BindTextureToFile: Invalid texture id for file %s\n", pFileName );
+ return;
+ }
+
+ CMatSystemTexture &texture = m_Textures[id];
+
+ // Reload from file if the material was never loaded, or if the filename has changed at all
+ CRC32_t fileNameCRC = Texture_CRCName( pFileName );
+ if ( !texture.GetMaterial() || fileNameCRC != texture.GetCRC() )
+ {
+ // New texture name
+ texture.SetCRC( fileNameCRC );
+ texture.SetMaterial( pFileName );
+ }
+}
+
+
+//-----------------------------------------------------------------------------
+// Binds a material to a texture
+//-----------------------------------------------------------------------------
+void CTextureDictionary::BindTextureToMaterial( int id, IMaterial *pMaterial )
+{
+ if (!IsValidId(id))
+ {
+ Msg( "BindTextureToFile: Invalid texture id %d\n", id );
+ return;
+ }
+
+ CMatSystemTexture &texture = m_Textures[id];
+ texture.SetMaterial( pMaterial );
+}
+
+
+//-----------------------------------------------------------------------------
+// Binds a material to a texture reference
+//-----------------------------------------------------------------------------
+void CTextureDictionary::BindTextureToMaterialReference( int id, int referenceId, IMaterial *pMaterial )
+{
+ if (!IsValidId(id) || !IsValidId(referenceId))
+ {
+ Msg( "BindTextureToFile: Invalid texture ids %d %d\n", id, referenceId );
+ return;
+ }
+
+ CMatSystemTexture &texture = m_Textures[id];
+ CMatSystemTexture &textureSource = m_Textures[referenceId];
+ texture.ReferenceOtherProcedural( &textureSource, pMaterial );
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the material associated with an id
+//-----------------------------------------------------------------------------
+IMaterial *CTextureDictionary::GetTextureMaterial( int id )
+{
+ if (!IsValidId(id))
+ return NULL;
+
+ return m_Textures[id].GetMaterial();
+}
+
+
+//-----------------------------------------------------------------------------
+// Returns the material size associated with an id
+//-----------------------------------------------------------------------------
+void CTextureDictionary::GetTextureSize(int id, int& iWide, int& iTall )
+{
+ if (!IsValidId(id))
+ {
+ iWide = iTall = 0;
+ return;
+ }
+
+ iWide = m_Textures[id].Width();
+ iTall = m_Textures[id].Height();
+}
+
+void CTextureDictionary::GetTextureTexCoords( int id, float &s0, float &t0, float &s1, float &t1 )
+{
+ if (!IsValidId(id))
+ {
+ s0 = t0 = 0.0f;
+ s1 = t1 = 1.0f;
+ return;
+ }
+
+ s0 = m_Textures[id].m_s0;
+ t0 = m_Textures[id].m_t0;
+ s1 = m_Textures[id].m_s1;
+ t1 = m_Textures[id].m_t1;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : id -
+// Output : CMatSystemTexture
+//-----------------------------------------------------------------------------
+CMatSystemTexture *CTextureDictionary::GetTexture( int id )
+{
+ if (!IsValidId(id))
+ return NULL;
+
+ return &m_Textures[ id ];
+}
+
+//-----------------------------------------------------------------------------
+// Purpose:
+// Input : *pFileName -
+//-----------------------------------------------------------------------------
+int CTextureDictionary::FindTextureIdForTextureFile( char const *pFileName )
+{
+ for ( int i = m_Textures.Head(); i != m_Textures.InvalidIndex(); i = m_Textures.Next( i ) )
+ {
+ CMatSystemTexture *tex = &m_Textures[i];
+ if ( !tex )
+ continue;
+
+ IMaterial *mat = tex->GetMaterial();
+ if ( !mat )
+ continue;
+
+ if ( !stricmp( mat->GetName(), pFileName ) )
+ return i;
+ }
+
+ return -1;
+}
diff --git a/vguimatsurface/TextureDictionary.h b/vguimatsurface/TextureDictionary.h
new file mode 100644
index 0000000..3fcb759
--- /dev/null
+++ b/vguimatsurface/TextureDictionary.h
@@ -0,0 +1,63 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Contains all texture state for the material system surface to use
+//
+// $Revision: $
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef TEXTUREDICTIONARY_H
+#define TEXTUREDICTIONARY_H
+
+class IMaterial;
+class ITexture;
+
+enum
+{
+ INVALID_TEXTURE_ID = -1
+};
+
+
+//-----------------------------------------------------------------------------
+// A class that manages textures used by the material system surface
+//-----------------------------------------------------------------------------
+class ITextureDictionary
+{
+public:
+ // Create, destroy textures
+ virtual int CreateTexture( bool procedural = false ) = 0;
+ virtual int CreateTextureByTexture( ITexture *pTexture, bool procedural = true ) = 0;
+ virtual void DestroyTexture( int id ) = 0;
+ virtual void DestroyAllTextures() = 0;
+
+ // Is this a valid id?
+ virtual bool IsValidId( int id ) const = 0;
+
+ // Binds a material to a texture
+ virtual void BindTextureToFile( int id, const char *pFileName ) = 0;
+
+ // Binds a material to a texture
+ virtual void BindTextureToMaterial( int id, IMaterial *pMaterial ) = 0;
+
+ // Binds a material to a texture
+ virtual void BindTextureToMaterialReference( int id, int referenceId, IMaterial *pMaterial ) = 0;
+
+ // Texture info
+ virtual IMaterial *GetTextureMaterial( int id ) = 0;
+ virtual void GetTextureSize(int id, int& iWide, int& iTall ) = 0;
+ virtual void GetTextureTexCoords( int id, float &s0, float &t0, float &s1, float &t1 ) = 0;
+
+ virtual void SetTextureRGBA( int id, const char* rgba, int wide, int tall ) = 0;
+
+ virtual int FindTextureIdForTextureFile( char const *pFileName ) = 0;
+ virtual void SetSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall ) = 0;
+ virtual void SetSubTextureRGBAEx( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat format ) = 0;
+
+ virtual void SetTextureRGBAEx( int id, const char* rgba, int wide, int tall, ImageFormat format, bool bFixupTextCoordsForDimensions ) = 0;
+
+ virtual void UpdateSubTextureRGBA( int id, int drawX, int drawY, unsigned const char *rgba, int subTextureWide, int subTextureTall, ImageFormat imageFormat ) = 0;
+};
+
+ITextureDictionary *TextureDictionary();
+
+#endif // TEXTUREDICTIONARY_H \ No newline at end of file
diff --git a/vguimatsurface/memorybitmap.cpp b/vguimatsurface/memorybitmap.cpp
new file mode 100644
index 0000000..4cf6d36
--- /dev/null
+++ b/vguimatsurface/memorybitmap.cpp
@@ -0,0 +1,181 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#include <vgui/ISurface.h>
+#include "memorybitmap.h"
+#include <string.h>
+#include <stdlib.h>
+#include "MatSystemSurface.h"
+#include "materialsystem/imaterialvar.h"
+#include "materialsystem/itexture.h"
+#include "bitmap/imageformat.h"
+#include "vtf/vtf.h"
+#include "KeyValues.h"
+#include "TextureDictionary.h"
+
+// memdbgon must be the last include file in a .cpp file!!!
+#include "tier0/memdbgon.h"
+
+extern CMatSystemSurface g_MatSystemSurface;
+
+using namespace vgui;
+
+//-----------------------------------------------------------------------------
+// Purpose: Constructor
+// Input : *filename - image file to load
+//-----------------------------------------------------------------------------
+MemoryBitmap::MemoryBitmap(unsigned char *texture,int wide, int tall)
+{
+ _texture=texture;
+ _uploaded = false;
+ _color = Color(255, 255, 255, 255);
+ _pos[0] = _pos[1] = 0;
+ _valid = true;
+ _w = wide;
+ _h = tall;
+ m_iTextureID = -1;
+
+ ForceUpload(texture,wide,tall);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: Destructor
+//-----------------------------------------------------------------------------
+MemoryBitmap::~MemoryBitmap()
+{
+ // Free the old texture ID.
+ if ( m_iTextureID != -1 )
+ {
+ TextureDictionary()->DestroyTexture( m_iTextureID );
+ m_iTextureID = -1;
+ }
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: data accessor
+//-----------------------------------------------------------------------------
+void MemoryBitmap::GetSize(int &wide, int &tall)
+{
+ wide = 0;
+ tall = 0;
+
+ if (!_valid)
+ return;
+
+ g_MatSystemSurface.DrawGetTextureSize(m_iTextureID, wide, tall);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: size of the bitmap
+//-----------------------------------------------------------------------------
+void MemoryBitmap::GetContentSize(int &wide, int &tall)
+{
+ GetSize(wide, tall);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: ignored
+//-----------------------------------------------------------------------------
+void MemoryBitmap::SetSize(int x, int y)
+{
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: data accessor
+//-----------------------------------------------------------------------------
+void MemoryBitmap::SetPos(int x, int y)
+{
+ _pos[0] = x;
+ _pos[1] = y;
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: data accessor
+//-----------------------------------------------------------------------------
+void MemoryBitmap::SetColor(Color col)
+{
+ _color = col;
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: returns the file name of the bitmap
+//-----------------------------------------------------------------------------
+const char *MemoryBitmap::GetName()
+{
+ return "MemoryBitmap";
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: Renders the loaded image, uploading it if necessary
+// Assumes a valid image is always returned from uploading
+//-----------------------------------------------------------------------------
+void MemoryBitmap::Paint()
+{
+ if (!_valid)
+ return;
+
+ // if we have not uploaded yet, lets go ahead and do so
+ if (!_uploaded)
+ {
+ ForceUpload(_texture,_w,_h);
+ }
+
+ //set the texture current, set the color, and draw the biatch
+ g_MatSystemSurface.DrawSetTexture(m_iTextureID);
+ g_MatSystemSurface.DrawSetColor(_color[0], _color[1], _color[2], _color[3]);
+
+ int wide, tall;
+ GetSize(wide, tall);
+ g_MatSystemSurface.DrawTexturedRect( _pos[0], _pos[1], _pos[0] + wide, _pos[1] + tall);
+}
+
+
+//-----------------------------------------------------------------------------
+// Purpose: ensures the bitmap has been uploaded
+//-----------------------------------------------------------------------------
+void MemoryBitmap::ForceUpload(unsigned char *texture,int wide, int tall)
+{
+ _texture=texture;
+ bool sizechanged = ( _w != wide || _h != tall );
+ _w = wide;
+ _h = tall;
+
+ if (!_valid)
+ return;
+
+ if(_w==0 || _h==0)
+ return;
+
+ // Not our first time through and the size changed, destroy and recreate texture id...
+ if ( m_iTextureID != -1 && sizechanged )
+ {
+ TextureDictionary()->DestroyTexture( m_iTextureID );
+ m_iTextureID = -1;
+ }
+
+ if ( m_iTextureID == -1 )
+ {
+ m_iTextureID = g_MatSystemSurface.CreateNewTextureID( true );
+ }
+
+ g_MatSystemSurface.DrawSetTextureRGBA( m_iTextureID, texture, wide, tall, true, true );
+
+ _uploaded = true;
+ _valid = g_MatSystemSurface.IsTextureIDValid(m_iTextureID);
+}
+
+//-----------------------------------------------------------------------------
+// Purpose: data accessor
+//-----------------------------------------------------------------------------
+HTexture MemoryBitmap::GetID()
+{
+ return m_iTextureID;
+}
+
+
diff --git a/vguimatsurface/memorybitmap.h b/vguimatsurface/memorybitmap.h
new file mode 100644
index 0000000..408daad
--- /dev/null
+++ b/vguimatsurface/memorybitmap.h
@@ -0,0 +1,63 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose:
+//
+// $NoKeywords: $
+//=============================================================================//
+
+#ifndef MEMORYBITMAP_H
+#define MEMORYBITMAP_H
+
+#ifdef _WIN32
+#pragma once
+#endif
+
+#include <vgui/VGUI.h>
+#include <vgui/IImage.h>
+#include <Color.h>
+
+namespace vgui
+{
+
+typedef unsigned long HTexture;
+
+//-----------------------------------------------------------------------------
+// Purpose: Holds a single image created from a chunk of memory, internal to vgui only
+//-----------------------------------------------------------------------------
+class MemoryBitmap: public IImage
+{
+public:
+ MemoryBitmap(unsigned char *texture,int wide, int tall);
+ ~MemoryBitmap();
+
+ // IImage implementation
+ virtual void Paint();
+ virtual void GetSize(int &wide, int &tall);
+ virtual void GetContentSize(int &wide, int &tall);
+ virtual void SetPos(int x, int y);
+ virtual void SetSize(int x, int y);
+ virtual void SetColor(Color col);
+
+ // methods
+ void ForceUpload(unsigned char *texture,int wide, int tall); // ensures the bitmap has been uploaded
+ HTexture GetID(); // returns the texture id
+ const char *GetName();
+ bool IsValid()
+ {
+ return _valid;
+ }
+
+private:
+// HTexture _id;
+ bool _uploaded;
+ bool _valid;
+ unsigned char *_texture;
+ int _pos[2];
+ Color _color;
+ int _w,_h; // size of the texture
+ int m_iTextureID;
+};
+
+} // namespace vgui
+
+#endif // MEMORYBITMAP_H
diff --git a/vguimatsurface/vguimatsurface.h b/vguimatsurface/vguimatsurface.h
new file mode 100644
index 0000000..2c73875
--- /dev/null
+++ b/vguimatsurface/vguimatsurface.h
@@ -0,0 +1,30 @@
+//========= Copyright Valve Corporation, All rights reserved. ============//
+//
+// Purpose: Implementation of the VGUI ISurface interface using the
+// material system to implement it
+//
+// $Revision: $
+// $NoKeywords: $
+//===========================================================================//
+
+#ifndef VGUIMATSURFACE_H
+#define VGUIMATSURFACE_H
+
+#include <vgui/VGUI.h>
+#include "tier3/tier3.h"
+
+
+namespace vgui
+{
+ class IInputInternal;
+}
+
+//-----------------------------------------------------------------------------
+// Globals...
+//-----------------------------------------------------------------------------
+extern vgui::IInputInternal *g_pIInput;
+
+
+#endif // VGUIMATSURFACE_H
+
+
diff --git a/vguimatsurface/vguimatsurface.vpc b/vguimatsurface/vguimatsurface.vpc
new file mode 100644
index 0000000..1f41c62
--- /dev/null
+++ b/vguimatsurface/vguimatsurface.vpc
@@ -0,0 +1,104 @@
+//-----------------------------------------------------------------------------
+// VGUIMATSURFACE.VPC
+//
+// Project Script
+//-----------------------------------------------------------------------------
+
+$macro SRCDIR ".."
+$Macro OUTBINDIR "$SRCDIR\..\game\bin"
+
+$include "$SRCDIR\vpc_scripts\source_dll_base.vpc"
+
+$Configuration
+{
+ $Compiler
+ {
+ $PreprocessorDefinitions "$BASE;BENCHMARK;VGUIMATSURFACE_DLL_EXPORT;GAMEUI_EXPORTS;DONT_PROTECT_FILEIO_FUNCTIONS;PROTECTED_THINGS_ENABLE"
+ $PreprocessorDefinitions "$BASE;fopen=dont_use_fopen" [$WIN32]
+ $EnableC++Exceptions "Yes (/EHsc)"
+// $TreatWchar_tAsBuiltinType "No"
+ }
+
+ $Linker
+ {
+ $SystemLibraries "iconv" [$OSXALL]
+ $SystemFrameworks "Carbon" [$OSXALL]
+ $GCC_ExtraLinkerFlags "-L/usr/lib32 -L/usr/lib -L/usr/lib/i386-linux-gnu" [$LINUXALL]
+ $SystemLibraries "fontconfig;freetype" [$LINUXALL]
+ $AdditionalDependencies "$BASE vgui_surfacelib_360.lib" [$X360]
+ $AdditionalDependencies "$BASE vgui_surfacelib.lib nvtc.lib" [$WIN32]
+ }
+}
+
+$Project "vguimatsurface"
+{
+ $Folder "Source Files"
+ {
+ $File "Clip2D.cpp"
+ $File "Cursor.cpp"
+ $File "$SRCDIR\public\filesystem_helpers.cpp"
+ $File "FontTextureCache.cpp"
+ $File "Input.cpp"
+ $File "MatSystemSurface.cpp"
+ $File "memorybitmap.cpp" [$WIN32]
+ $File "TextureDictionary.cpp"
+ $File "$SRCDIR\vgui2\src\vgui_key_translation.cpp"
+ $File "$SRCDIR\public\vgui_controls\vgui_controls.cpp"
+ }
+
+ $Folder "Header Files"
+ {
+ $File "Clip2D.h"
+ $File "Cursor.h"
+ $File "Input.h"
+ $File "memorybitmap.h" [$WIN32]
+ $File "TextureDictionary.h"
+ $File "vguimatsurface.h"
+ $File "MatSystemSurface.h"
+ $File "FontTextureCache.h"
+ $File "$SRCDIR\vgui2\src\vgui_key_translation.h"
+ }
+
+ $Folder "Public Header Files"
+ {
+ $File "$SRCDIR\public\tier0\basetypes.h"
+ $File "$SRCDIR\public\tier1\characterset.h"
+ $File "$SRCDIR\public\tier1\checksum_crc.h"
+ $File "$SRCDIR\public\tier0\commonmacros.h"
+ $File "$SRCDIR\public\filesystem.h"
+ $File "$SRCDIR\public\filesystem_helpers.h"
+ $File "$SRCDIR\common\vgui_surfacelib\FontAmalgam.h"
+ $File "$SRCDIR\common\vgui_surfacelib\FontManager.h"
+ $File "$SRCDIR\public\appframework\IAppSystem.h"
+ $File "$SRCDIR\public\materialsystem\imaterial.h"
+ $File "$SRCDIR\public\materialsystem\imaterialsystem.h"
+ $File "$SRCDIR\public\materialsystem\imaterialvar.h"
+ $File "$SRCDIR\public\VGuiMatSurface\IMatSystemSurface.h"
+ $File "$SRCDIR\public\materialsystem\imesh.h"
+ $File "$SRCDIR\public\tier1\interface.h"
+ $File "$SRCDIR\public\materialsystem\itexture.h"
+ $File "$SRCDIR\public\pixelwriter.h"
+ $File "$SRCDIR\public\tier1\strtools.h"
+ $File "$SRCDIR\public\tier1\utllinkedlist.h"
+ $File "$SRCDIR\public\tier1\utlmemory.h"
+ $File "$SRCDIR\public\tier1\utlrbtree.h"
+ $File "$SRCDIR\public\tier1\utlvector.h"
+ $File "$SRCDIR\public\mathlib\vector.h"
+ $File "$SRCDIR\public\mathlib\vector2d.h"
+ $File "$SRCDIR\public\mathlib\vector4d.h"
+ $File "$SRCDIR\public\vstdlib\vstdlib.h"
+ $File "$SRCDIR\public\vtf\vtf.h"
+ $File "$SRCDIR\common\vgui_surfacelib\Win32Font.h"
+ }
+
+ $Folder "Link Libraries"
+ {
+ $Lib bitmap
+ $Lib mathlib
+ $Lib tier2
+ $Lib tier3
+ $Lib vgui_controls
+ $Lib vgui_surfacelib
+ $ImpLib SDL2 [$SDL]
+ }
+}
diff --git a/vguimatsurface/xbox/xbox.def b/vguimatsurface/xbox/xbox.def
new file mode 100644
index 0000000..f907212
--- /dev/null
+++ b/vguimatsurface/xbox/xbox.def
@@ -0,0 +1,3 @@
+LIBRARY vguimatsurface_360.dll
+EXPORTS
+ CreateInterface @1