This commit is contained in:
nephacks
2025-06-04 03:22:50 +02:00
parent f234f23848
commit f12416cffd
14243 changed files with 6446499 additions and 26 deletions

View File

@@ -0,0 +1,820 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "gamelayer.h"
#include "gamerect.h"
#include "tier1/keyvalues.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "tier1/utlbuffer.h"
#include "tier2/tier2.h"
#include "filesystem.h"
#include "rendersystem/irendercontext.h"
#include "tier2/fileutils.h"
#include "gameuisystemsurface.h"
#include "gameuidefinition.h"
#include "tier1/fmtstr.h"
#include "gamerect.h"
#include "gametext.h"
#include "hitarea.h"
#include "graphicgroup.h"
#include "dynamicrect.h"
#include "gameuiscript.h"
#include "gameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_DMXELEMENT_UNPACK ( CGameLayer )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
END_DMXELEMENT_UNPACK( CGameLayer, s_GameLayerUnpack )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameLayer::CGameLayer( SublayerTypes_t layerType )
{
m_pName = "";
m_LayerType = layerType;
m_pTextureName = "";
m_hTexture = RENDER_TEXTURE_HANDLE_INVALID;
m_Material = NULL;
m_Sheet = NULL;
m_SheetSymbol = UTL_INVAL_SYMBOL;
m_bSheetSymbolCached = false;
}
//-----------------------------------------------------------------------------
// Destructor
//-----------------------------------------------------------------------------
CGameLayer::~CGameLayer()
{
if ( m_Material.IsValid() )
{
m_Material.Shutdown( true );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::Shutdown()
{
int nGraphicsCount = m_LayerGraphics.Count();
for ( int j = 0; j < nGraphicsCount; ++j )
{
Assert( !m_LayerGraphics[j]->IsGroup() );
delete m_LayerGraphics[j];
m_LayerGraphics[j] = NULL;
}
m_LayerGraphics.RemoveAll();
}
//-----------------------------------------------------------------------------
// Load data from dmx file
//-----------------------------------------------------------------------------
bool CGameLayer::Unserialize( CDmxElement *pLayer, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping )
{
pLayer->UnpackIntoStructure( this, s_GameLayerUnpack );
// Static graphics
if ( m_LayerType == SUBLAYER_STATIC )
{
CDmxAttribute *pGraphics = pLayer->GetAttribute( "staticGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphics->GetArray< CDmxElement * >( );
int nCount = graphics.Count();
for ( int i = 0; i < nCount; ++i )
{
// What kind of graphic is this?
const char *pType = graphics[i]->GetValueString( "classtype" );
if ( !Q_stricmp( pType, "CDmeRectGeometry" ) )
{
CGameRect *pGraphic = new CGameRect( "" );
if ( !pGraphic->Unserialize( graphics[i] ) )
{
delete pGraphic;
return false;
}
m_LayerGraphics.AddToTail( pGraphic );
char pBuf[255];
UniqueIdToString( graphics[i]->GetId(), pBuf, 255 );
unserializedGraphicMapping.Insert( pBuf, pGraphic );
}
else if ( !Q_stricmp( pType, "CDmeHitAreaGeometry" ) )
{
CHitArea *pGraphic = new CHitArea( "" );
if ( !pGraphic->Unserialize( graphics[i] ) )
{
delete pGraphic;
return false;
}
m_LayerGraphics.AddToTail( pGraphic );
char pBuf[255];
UniqueIdToString( graphics[i]->GetId(), pBuf, 255 );
unserializedGraphicMapping.Insert( pBuf, pGraphic );
}
else
{
Warning( "CGameUIDefinition: Warning unknown static graphic type\n" );
}
}
CDmxAttribute *pTextureName = pLayer->GetAttribute( "statictexture" );
if ( !pTextureName || pTextureName->GetType() != AT_STRING )
{
return false;
}
char textureName[128];
pTextureName->GetValueAsString( textureName, 128 );
InitSheetTexture( textureName );
}
// Dynamic graphics
else if ( m_LayerType == SUBLAYER_DYNAMIC )
{
CDmxAttribute *pGraphicsAttr = pLayer->GetAttribute( "dynamicGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphicsAttr->GetArray< CDmxElement * >( );
for ( int i = 0; i < graphics.Count(); ++i )
{
// What kind of graphic is this?
const char *pType = graphics[i]->GetValueString( "classtype" );
if ( !Q_stricmp( pType, "CDmeDynamicRectGeometry" ) )
{
CDynamicRect *pGraphic = new CDynamicRect( "" );
if ( !pGraphic->Unserialize( graphics[i] ) )
{
delete pGraphic;
return false;
}
m_LayerGraphics.AddToTail( pGraphic );
char pBuf[255];
UniqueIdToString( graphics[i]->GetId(), pBuf, 255 );
unserializedGraphicMapping.Insert( pBuf, pGraphic );
}
else
{
Warning( "CGameUIDefinition: Warning unknown static graphic type\n" );
}
}
}
// Font graphics
else if ( m_LayerType == SUBLAYER_FONT )
{
CDmxAttribute *pGraphics = pLayer->GetAttribute( "fontGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphics->GetArray< CDmxElement * >( );
int nCount = graphics.Count();
for ( int i = 0; i < nCount; ++i )
{
// What kind of graphic is this?
const char *pType = graphics[i]->GetValueString( "classtype" );
if ( !Q_stricmp( pType, "CDmeTextGeometry" ) )
{
CGameText *pGraphic = new CGameText( "" );
if ( !pGraphic->Unserialize( graphics[i] ) )
{
delete pGraphic;
return false;
}
m_LayerGraphics.AddToTail( pGraphic );
char pBuf[255];
UniqueIdToString( graphics[i]->GetId(), pBuf, 255 );
GameGraphicMap_t graphicMapEntry;
graphicMapEntry.m_Id = graphics[i]->GetId();
graphicMapEntry.pGraphic = pGraphic;
unserializedGraphicMapping.Insert( pBuf, pGraphic );
}
else
{
Warning( "CGameUIDefinition: Warning unknown font graphic type in gui file.\n" );
}
}
}
else
{
Assert(0); // Unknown layer type!!
}
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CGameLayer::InitSheetTexture()
{
Assert( m_pTextureName );
return InitSheetTexture( m_pTextureName );
}
//-----------------------------------------------------------------------------
// FIXME: Must go into rendersystem at some point
//-----------------------------------------------------------------------------
static HRenderTexture CreateTextureFromVTFFile( const char *pFileName, CSheet **ppSheet )
{
static intp s_UniqueID = 0x4000000;
*ppSheet = NULL;
char pTemp[MAX_PATH];
Q_ComposeFileName( "materials/", pFileName, pTemp, sizeof(pTemp) );
Q_SetExtension( pTemp, "vtf", sizeof(pTemp) );
pFileName = pTemp;
char pTemp360[MAX_PATH];
if ( PLATFORM_EXT[0] )
{
CreatePlatformFilename( pFileName, pTemp360, sizeof(pTemp360) );
pFileName = pTemp360;
}
CUtlBuffer fBuf;
if ( !g_pFullFileSystem->ReadFile( pFileName, "GAME", fBuf ) )
{
Warning( "Unable to read texture file %s\n", pFileName );
return RENDER_TEXTURE_HANDLE_INVALID;
}
IVTFTexture *pVtfTexture = CreateVTFTexture();
#if !defined( _GAMECONSOLE )
pVtfTexture->Unserialize( fBuf );
#else
pVtfTexture->UnserializeFromBuffer( fBuf, true, false, false, 0 );
#endif
// we are only going to load the high mip
// pCurData is pointing at pixel data now
TextureHeader_t spec;
memset( &spec, 0, sizeof(TextureHeader_t) );
spec.m_nWidth = pVtfTexture->Width();
spec.m_nHeight = pVtfTexture->Height();
spec.m_nNumMipLevels = 1; //pVtfTexture->MipCount();
spec.m_nDepth = pVtfTexture->Depth();
spec.m_nImageFormat = pVtfTexture->Format();
//spec.m_vecAverageColor.Init( pVtfTexture->Reflectivity().x, pVtfTexture->Reflectivity().y, pVtfTexture->Reflectivity().z, 1 );
char pResourceName[16];
Q_snprintf( pResourceName, sizeof(pResourceName), "%d", s_UniqueID );
HRenderTexture hRet = g_pRenderDevice->FindOrCreateTexture( "gamelayer", pResourceName, &spec );
ResourceAddRef( hRet );
s_UniqueID++;
IRenderContext *pCtx = g_pRenderDevice->GetRenderContext( );
pCtx->SetTextureData( hRet, &spec, pVtfTexture->ImageData( 0, 0, 0 ), pVtfTexture->ComputeTotalSize(), pVtfTexture->IsPreTiled() );
pCtx->Submit( );
g_pRenderDevice->ReleaseRenderContext( pCtx );
ResourceRelease( hRet );
size_t nSheetByteCount;
const void *pSheetData = pVtfTexture->GetResourceData( VTF_RSRC_SHEET, &nSheetByteCount );
if ( pSheetData )
{
// expand compact sheet into fatter runtime form
CUtlBuffer bufLoad( pSheetData, nSheetByteCount, CUtlBuffer::READ_ONLY );
*ppSheet = new CSheet( bufLoad );
}
DestroyVTFTexture( pVtfTexture );
return hRet;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CGameLayer::InitSheetTexture( const char *pBaseTextureName )
{
m_pTextureName = pBaseTextureName;
if ( !g_pRenderDevice )
{
// Material names must be different for each menu.
CFmtStr materialName;
switch ( m_LayerType )
{
case SUBLAYER_STATIC:
materialName.sprintf( "statictx_%s", pBaseTextureName );
break;
case SUBLAYER_DYNAMIC:
materialName.sprintf( "dynamictx_%s", pBaseTextureName );
break;
case SUBLAYER_FONT:
materialName.sprintf( "fonttx_%s", pBaseTextureName );
break;
default:
Assert(0);
break;
};
KeyValues *pVMTKeyValues = new KeyValues( "GameControls" );
pVMTKeyValues->SetString( "$basetexture", pBaseTextureName );
m_Material.Init( materialName, TEXTURE_GROUP_OTHER, pVMTKeyValues );
m_Material->Refresh();
m_Sheet.Set( LoadSheet( m_Material ) );
}
else
{
CUtlString materialName;
switch ( m_LayerType )
{
case SUBLAYER_STATIC:
CSheet *pSheet;
m_hTexture = CreateTextureFromVTFFile( pBaseTextureName, &pSheet );
m_Sheet.Set( pSheet );
break;
case SUBLAYER_DYNAMIC:
break;
case SUBLAYER_FONT:
break;
default:
Assert(0);
break;
};
}
return true;
}
//-----------------------------------------------------------------------------
// UI sheets
//-----------------------------------------------------------------------------
CSheet *CGameLayer::LoadSheet( IMaterial *pMaterial )
{
if ( !pMaterial )
return NULL;
bool bFoundVar = false;
IMaterialVar *pVar = pMaterial->FindVar( "$basetexture", &bFoundVar, true );
if ( bFoundVar && pVar && pVar->IsDefined() )
{
ITexture *pTex = pVar->GetTextureValue();
if ( pTex && !pTex->IsError() )
{
return LoadSheet( pTex->GetName(), pTex );
}
}
return NULL;
}
void CGameLayer::GetSheetTextureSize( int &nWidth, int &nHeight )
{
if ( !m_Material )
return;
bool bFoundVar = false;
IMaterialVar *pVar = m_Material->FindVar( "$basetexture", &bFoundVar, true );
if ( bFoundVar && pVar && pVar->IsDefined() )
{
ITexture *pTex = pVar->GetTextureValue();
if ( pTex && !pTex->IsError() )
{
nWidth = pTex->GetActualWidth();
nHeight = pTex->GetActualHeight();
}
}
}
//--------------------------------------------------------------------------------
// UI sheets
//--------------------------------------------------------------------------------
CSheet *CGameLayer::LoadSheet( char const *pszFname, ITexture *pTexture )
{
//if ( !m_bShouldLoadSheets )
// return NULL;
//if ( m_SheetList.Defined( pszFname ) )
// return m_SheetList[ pszFname ];
CSheet *pNewSheet = NULL;
// get compact sheet representation held by texture
size_t numBytes;
void const *pSheet = pTexture->GetResourceData( VTF_RSRC_SHEET, &numBytes );
if ( pSheet )
{
// expand compact sheet into fatter runtime form
CUtlBuffer bufLoad( pSheet, numBytes, CUtlBuffer::READ_ONLY );
pNewSheet = new CSheet( bufLoad );
}
//m_SheetList[ pszFname ] = pNewSheet;
return pNewSheet;
}
//--------------------------------------------------------------------------------
// Add a graphic to the list.
//--------------------------------------------------------------------------------
int CGameLayer::AddGraphic( CGameGraphic *pGraphic )
{
return m_LayerGraphics.AddToTail( pGraphic );
}
//--------------------------------------------------------------------------------
// Remove a graphic from the list.
// Returns true if it was found and removed.
//--------------------------------------------------------------------------------
bool CGameLayer::RemoveGraphic( CGameGraphic *pGraphic )
{
return m_LayerGraphics.FindAndRemove( pGraphic );
}
//--------------------------------------------------------------------------------
// Clear out the graphics list
//--------------------------------------------------------------------------------
void CGameLayer::ClearGraphics()
{
m_LayerGraphics.RemoveAll();
}
//--------------------------------------------------------------------------------
// Clear out the graphics list
//--------------------------------------------------------------------------------
bool CGameLayer::HasGraphic( CGameGraphic *pGraphic )
{
int nCount = m_LayerGraphics.Count();
for ( int i = 0; i < nCount; ++i )
{
if ( pGraphic == m_LayerGraphics[i] )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial *CGameLayer::GetMaterial()
{
// FIXME
// NOTE: This has to be this way to ensure we don't load every freaking material @ startup
//Assert( IsPrecached() );
//if ( !IsPrecached() )
// return NULL;
return m_Material;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::InvalidateSheetSymbol()
{
m_bSheetSymbolCached = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::CacheSheetSymbol( CUtlSymbol sheetSymbol )
{
m_SheetSymbol = sheetSymbol;
m_bSheetSymbolCached = true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CUtlSymbol CGameLayer::GetSheetSymbol() const
{
Assert( IsSheetSymbolCached() );
return m_SheetSymbol;
}
//-----------------------------------------------------------------------------
// Start playing animations
//-----------------------------------------------------------------------------
void CGameLayer::StartPlaying()
{
int nCount = m_LayerGraphics.Count();
for ( int i = 0; i < nCount; ++i )
{
m_LayerGraphics[i]->StartPlaying();
}
}
//-----------------------------------------------------------------------------
// Stop playing animations
//-----------------------------------------------------------------------------
void CGameLayer::StopPlaying()
{
int nCount = m_LayerGraphics.Count();
for ( int i = 0; i < nCount; ++i )
{
m_LayerGraphics[i]->StopPlaying();
}
}
//-----------------------------------------------------------------------------
// Move to the next available animation state
//-----------------------------------------------------------------------------
void CGameLayer::AdvanceState()
{
int nCount = m_LayerGraphics.Count();
for ( int i = 0; i < nCount; ++i )
{
m_LayerGraphics[i]->AdvanceState();
}
}
//-----------------------------------------------------------------------------
// Set all graphics to "default" state.
//-----------------------------------------------------------------------------
void CGameLayer::InitAnims()
{
int nCount = m_LayerGraphics.Count();
for ( int i = 0; i < nCount; ++i )
{
m_LayerGraphics[i]->SetState( "default" );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::UpdateGeometry()
{
int nGraphicsCount = m_LayerGraphics.Count();
if ( nGraphicsCount == 0 )
{
return;
}
for ( int i = 0; i < nGraphicsCount; ++i )
{
m_LayerGraphics[i]->UpdateGeometry();
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo )
{
int nGraphicsCount = m_LayerGraphics.Count();
if ( nGraphicsCount == 0 )
{
return;
}
for ( int i = 0; i < nGraphicsCount; ++i )
{
m_LayerGraphics[i]->UpdateRenderTransforms( stageRenderInfo );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameLayer::UpdateRenderData( CGameUIDefinition &gameUIDef, color32 parentColor, CUtlVector< LayerRenderLists_t > &renderLists )
{
bool bDrawExtents = false;
int nGraphicsCount = m_LayerGraphics.Count();
if ( nGraphicsCount == 0 )
{
return;
}
// Basic algorithm is one renderList per material.
// Static graphics are sorted so that they all use the same sheet texture.
// Font graphics are sorted by render order. Their rendergeometry contains the font ID to use
// Dynamic graphics could add renderlists, since the material can change.
// Dynamic graphics will keep adding to the same renderlist until the material's don't match.
// This adds draw calls but preserves render order.
if ( m_LayerType == SUBLAYER_DYNAMIC )
{
int listIndex = -1;
int layerIndex = -1;
for ( int i = 0; i < nGraphicsCount; ++i )
{
// Groups should never be in lists of layer graphics.
Assert( !m_LayerGraphics[i]->IsGroup() );
CGraphicGroup *pGroup = m_LayerGraphics[i]->GetGroup();
Assert( pGroup );
// Only dynamic graphics are allowed in dynamic sublayers.
Assert( m_LayerGraphics[i]->IsDynamic() );
// Get the material this graphic uses.
const char *pAlias = m_LayerGraphics[i]->GetMaterialAlias();
IMaterial *pAliasMaterial = g_pGameUISystemMgrImpl->GetImageAliasMaterial( pAlias );
// Is the material this graphic uses the same as the one in our current renderlist?
if ( i == 0 || renderLists[layerIndex].m_pMaterial != pAliasMaterial )
{
// Our material has changed. Add a new renderlist for this material.
layerIndex = renderLists.AddToTail();
listIndex = renderLists[layerIndex].m_RenderGeometryLists.AddToTail();
renderLists[layerIndex].m_LayerType = m_LayerType;
renderLists[layerIndex].m_pMaterial = pAliasMaterial;
renderLists[layerIndex].m_pSheet = NULL;
renderLists[layerIndex].m_hTexture = m_hTexture;
}
CUtlVector< RenderGeometryList_t > &renderGeometryLists = renderLists[layerIndex].m_RenderGeometryLists;
Assert( layerIndex != -1 );
Assert( listIndex != -1 );
m_LayerGraphics[i]->UpdateRenderData( pGroup->GetResultantColor(), renderGeometryLists, listIndex );
}
}
else if ( m_LayerType == SUBLAYER_STATIC )
{
int listIndex = -1;
int layerIndex = -1;
layerIndex = renderLists.AddToTail();
listIndex = renderLists[layerIndex].m_RenderGeometryLists.AddToTail();
renderLists[layerIndex].m_LayerType = m_LayerType;
renderLists[layerIndex].m_pMaterial = m_Material;
renderLists[layerIndex].m_pSheet = m_Sheet;
renderLists[layerIndex].m_hTexture = m_hTexture;
CUtlVector< RenderGeometryList_t > &renderGeometryLists = renderLists[layerIndex].m_RenderGeometryLists;
Assert( layerIndex != -1 );
Assert( listIndex != -1 );
for ( int i = 0; i < nGraphicsCount; ++i )
{
// Groups should never be in lists of layer graphics.
Assert( !m_LayerGraphics[i]->IsGroup() );
CGraphicGroup *pGroup = m_LayerGraphics[i]->GetGroup();
Assert( pGroup );
m_LayerGraphics[i]->UpdateRenderData( pGroup->GetResultantColor(), renderGeometryLists, listIndex );
}
if ( bDrawExtents )
{
for ( int i = 0; i < nGraphicsCount; ++i )
{
if ( !m_LayerGraphics[i]->IsGroup() )
{
m_LayerGraphics[i]->DrawExtents( renderGeometryLists, listIndex );
}
}
}
}
else if ( m_LayerType == SUBLAYER_FONT )
{
int listIndex = -1;
int layerIndex = -1;
layerIndex = renderLists.AddToTail();
listIndex = renderLists[layerIndex].m_RenderGeometryLists.AddToTail();
renderLists[layerIndex].m_LayerType = m_LayerType;
renderLists[layerIndex].m_pMaterial = m_Material;
renderLists[layerIndex].m_pSheet = m_Sheet;
renderLists[layerIndex].m_hTexture = m_hTexture;
CUtlVector< RenderGeometryList_t > &renderGeometryLists = renderLists[layerIndex].m_RenderGeometryLists;
Assert( layerIndex != -1 );
Assert( listIndex != -1 );
for ( int i = 0; i < nGraphicsCount; ++i )
{
// Groups should never be in lists of layer graphics.
Assert( !m_LayerGraphics[i]->IsGroup() );
CGraphicGroup *pGroup = m_LayerGraphics[i]->GetGroup();
Assert( pGroup );
m_LayerGraphics[i]->UpdateRenderData( pGroup->GetResultantColor(), renderGeometryLists, listIndex );
}
if ( bDrawExtents )
{
// Find the static material and sheet
for ( int i = 0; i < renderLists.Count(); ++i )
{
if ( renderLists[i].m_LayerType == SUBLAYER_STATIC )
{
// Make another layer for rendering extents
// Only do this if there is a static texture around to use for rendering.
layerIndex = renderLists.AddToTail();
listIndex = renderLists[layerIndex].m_RenderGeometryLists.AddToTail();
renderLists[layerIndex].m_LayerType = SUBLAYER_STATIC; // must be static since these render as triangles.
renderLists[layerIndex].m_pMaterial = renderLists[i].m_pMaterial;
renderLists[layerIndex].m_pSheet = renderLists[i].m_pSheet;
renderLists[layerIndex].m_hTexture = renderLists[i].m_hTexture;
CUtlVector< RenderGeometryList_t > &renderGeometryLists2 = renderLists[layerIndex].m_RenderGeometryLists;
Assert( layerIndex != -1 );
Assert( listIndex != -1 );
for ( int i = 0; i < nGraphicsCount; ++i )
{
CGameText *pText = dynamic_cast<CGameText *>( m_LayerGraphics[i] );
Assert( pText );
pText->DrawExtents( renderGeometryLists2, listIndex );
}
break;
}
}
}
}
}
//-----------------------------------------------------------------------------
// Given a position, return the front most graphic under it.
//-----------------------------------------------------------------------------
CGameGraphic *CGameLayer::GetGraphic( int x, int y )
{
int nGraphicCount = m_LayerGraphics.Count();
for ( int i = nGraphicCount-1; i >= 0; --i )
{
CGameGraphic *pGraphic = m_LayerGraphics[i];
if ( pGraphic->HitTest( x, y ) )
return pGraphic;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Given a position, return the front most graphic that can take input under it.
//-----------------------------------------------------------------------------
CGameGraphic *CGameLayer::GetMouseFocus( int x, int y )
{
int nGraphicCount = m_LayerGraphics.Count();
for ( int i = nGraphicCount-1; i >= 0; --i )
{
CGameGraphic *pGraphic = m_LayerGraphics[i];
if ( pGraphic->CanAcceptInput() && pGraphic->HitTest( x, y ) )
return pGraphic;
}
return NULL;
}
//-----------------------------------------------------------------------------
// Given a position, return the front most graphic that can take input under it.
//-----------------------------------------------------------------------------
CGameGraphic *CGameLayer::GetNextFocus( bool &bGetNext, CGameGraphic *pCurrentGraphic )
{
int nGraphicCount = m_LayerGraphics.Count();
for ( int i = 0; i < nGraphicCount; ++i )
{
CGameGraphic *pGraphic = m_LayerGraphics[i];
if ( bGetNext && pGraphic->CanAcceptInput() )
{
return pGraphic;
}
if ( pCurrentGraphic == pGraphic )
{
bGetNext = true;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Given a name of a graphic, find it in this layer
//-----------------------------------------------------------------------------
CGameGraphic *CGameLayer::FindGraphicByName( const char *pName )
{
int nGraphicCount = m_LayerGraphics.Count();
for ( int i = 0; i < nGraphicCount; ++i )
{
CGameGraphic *pGraphic = m_LayerGraphics[i]->FindGraphicByName( pName );
if ( pGraphic )
{
// Match.
return pGraphic;
}
}
return NULL;
}

View File

@@ -0,0 +1,767 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
//=============================================================================
#include "gameuisystem.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "gameuidefinition.h"
#include "gamelayer.h"
#include "tier0/vprof.h"
#include "rendersystem/irenderdevice.h"
#include "rendersystem/irendercontext.h"
#include "gameuisystemsurface.h"
#include "inputgameui.h"
#include "gameuisystemmgr.h"
#include "gameuiscript.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define MAX_LAYERS 10
#define DEBUG_DRAW_REPORT 1
#define HIDE_ALL_TEXT 0
#define HIDE_FONT_TEXTURES 1
// A list of script handles exposed by the system
static int32 g_iSerialHandle = 0;
static CUtlMap< int32, CGameUISystem * > g_mapScriptHandles( DefLessFunc( int32 ) );
CGameUISystem::CGameUISystem() :
m_GameUIDef( this ),
m_iScriptHandle( ++g_iSerialHandle )
{
m_bDrawReport = true;
g_mapScriptHandles.InsertOrReplace( m_iScriptHandle, this );
}
CGameUISystem::~CGameUISystem()
{
g_mapScriptHandles.Remove( m_iScriptHandle );
}
CGameUISystem * CGameUISystem::FromScriptHandle( int32 iScriptHandle )
{
unsigned short usIdx = g_mapScriptHandles.Find( iScriptHandle );
return ( usIdx == g_mapScriptHandles.InvalidIndex() ) ? NULL : g_mapScriptHandles.Element( usIdx );
}
char const * CGameUISystem::GetName()
{
return m_GameUIDef.GetName();
}
//-----------------------------------------------------------------------------
// Init, shutdown
//-----------------------------------------------------------------------------
bool CGameUISystem::Init( KeyValues *kvLoadSettings )
{
DevMsg( "CGameUISystem[%p]::Init( name = %s )\n", this, GetName() );
KeyValuesDumpAsDevMsg( kvLoadSettings );
return true;
}
void CGameUISystem::Release()
{
DevMsg( "CGameUISystem[%p]::Release( name = %s )\n", this, GetName() );
g_pGameUISystemMgrImpl->OnScreenReleased( this );
m_GameUIDef.Shutdown();
delete this;
}
//-----------------------------------------------------------------------------
// Creates an empty game UI.
//-----------------------------------------------------------------------------
void CGameUISystem::LoadEmptyGameUI( const char *pName )
{
m_GameUIDef.Shutdown();
m_GameUIDef.CreateDefault( pName );
}
//-----------------------------------------------------------------------------
// Read the game UI config file from a utlbuffer
//-----------------------------------------------------------------------------
bool CGameUISystem::LoadGameUIDefinition( CUtlBuffer &buf, const char *pFileName )
{
DECLARE_DMX_CONTEXT();
CDmxElement *pRoot = NULL;
if ( !UnserializeDMX( buf, &pRoot, pFileName ) )
{
Warning( "Unable to read game UI config %s! UtlBuffer is the wrong type!\n", pFileName );
return false;
}
bool bOk = m_GameUIDef.Unserialize( pRoot );
CleanupDMX( pRoot );
if ( !bOk )
return false;
m_GameUIDef.InitializeScripts();
// Start the animations all at the same time.
//Start();
//TextTest();
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CGameUISystem::ExecuteScript( KeyValues *kvEvent, KeyValues **ppResult )
{
return m_GameUIDef.ExecuteScript( kvEvent, ppResult );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUISystem::SetStageSize( int nWide, int nTall )
{
m_GameUIDef.SetStageSize( nWide, nTall);
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUISystem::GetStageSize( Vector2D &stageSize )
{
m_GameUIDef.GetStageSize( stageSize );
}
//-----------------------------------------------------------------------------
// 3 draw calls per layer.
// Render in source 1
//-----------------------------------------------------------------------------
void CGameUISystem::Render( const Rect_t &viewport )
{
if ( !m_GameUIDef.GetVisible() )
return;
VPROF_BUDGET( "Render", "Render" );
Assert( g_pMaterialSystem );
m_GameUIDef.UpdateGeometry();
m_GameUIDef.UpdateRenderTransforms( viewport );
CUtlVector< LayerRenderLists_t > renderLists;
m_GameUIDef.GetRenderData( renderLists );
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
// Clear back buffer to green. Useful for debugging graphics that you think should be there and are not.
//pRenderContext->ClearColor4ub( 76, 88, 68, 255 );
//pRenderContext->ClearBuffers( true, true );
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Scale( 1, -1, 1 );
float flPixelOffsetX = .5;
float flPixelOffsetY = .5;
pRenderContext->Ortho( viewport.x + flPixelOffsetX, viewport.y + flPixelOffsetY, viewport.width + flPixelOffsetX, viewport.height + flPixelOffsetY, -1.0f, 1.0f );
// make sure there is no translation and rotation laying around
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
int nStaticDrawCalls = 0;
int nDynamicDrawCalls = 0;
int nFontDrawCalls = 0;
int nLists = renderLists.Count();
for ( int i = 0; i < nLists; ++i )
{
if ( renderLists[i].m_LayerType == SUBLAYER_STATIC )
{
for ( int j = 0; j < renderLists[i].m_RenderGeometryLists.Count(); ++j )
{
RenderStaticLayer( renderLists[i], j );
nStaticDrawCalls++;
}
}
else if ( renderLists[i].m_LayerType == SUBLAYER_DYNAMIC )
{
// For dynamic texture viewing.
//int x = 900;
//int y = 0;
for ( int j = 0; j < renderLists[i].m_RenderGeometryLists.Count(); ++j )
{
RenderDynamicLayer( renderLists[i], j );
nDynamicDrawCalls++;
// For dynamic texture viewing.
//g_pGameUISystemMgrImpl->DrawDynamicTexture( renderLists[i].m_RenderGeometryLists[j][0].m_pImageAlias, x, y );
//y += 256 + 30;
}
}
else if ( renderLists[i].m_LayerType == SUBLAYER_FONT )
{
// For font texture viewing.
//int x = 900;
//int y = 30;
for ( int j = 0; j < renderLists[i].m_RenderGeometryLists.Count(); ++j )
{
RenderTextLayer( renderLists[i].m_RenderGeometryLists[j] );
nFontDrawCalls++;
// For font texture viewing.
//g_pGameUISystemSurface->DrawFontTexture( renderLists[i].m_RenderGeometryLists[j][0].m_FontTextureID, x, y );
//y += 256 + 30;
}
}
}
#if ( DEBUG_DRAW_REPORT )
if ( m_bDrawReport )
{
m_bDrawReport = false;
Msg( "Total static draw calls in UI: %d\n", nStaticDrawCalls );
Msg( "Total dynamic draw calls in UI: %d\n", nDynamicDrawCalls );
Msg( "Total font draw calls in UI: %d\n", nFontDrawCalls );
Msg( "Total draw calls in UI: %d\n", nStaticDrawCalls + nDynamicDrawCalls + nFontDrawCalls );
}
#endif
// Restore the matrices
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
}
//-----------------------------------------------------------------------------
// Render a static layer in source 1
//-----------------------------------------------------------------------------
void CGameUISystem::RenderStaticLayer( LayerRenderLists_t &renderList, int geometryIndex )
{
// Do not call draw on an empty mesh.
int nTotalTriCount = 0;
for( int i = 0; i < renderList.m_RenderGeometryLists[geometryIndex].Count(); ++i )
{
nTotalTriCount += renderList.m_RenderGeometryLists[geometryIndex][i].GetTriangleCount();
}
if ( nTotalTriCount == 0 )
return;
if ( renderList.m_pSheet == NULL )
{
Assert(0);
return;
}
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->Bind( renderList.m_pMaterial, NULL );
IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
GenerateUIMesh( pRenderContext, pMesh, renderList.m_RenderGeometryLists[geometryIndex],
renderList.m_pSheet );
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Render a dynamic layer in source 1
//-----------------------------------------------------------------------------
void CGameUISystem::RenderDynamicLayer( LayerRenderLists_t &renderList, int geometryIndex )
{
// Do not call draw on an empty mesh.
int nTotalTriCount = 0;
for( int i = 0; i < renderList.m_RenderGeometryLists[geometryIndex].Count(); ++i )
{
nTotalTriCount += renderList.m_RenderGeometryLists[geometryIndex][i].GetTriangleCount();
}
if ( nTotalTriCount == 0 )
return;
if ( renderList.m_pMaterial == NULL )
return;
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
IMesh* pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, renderList.m_pMaterial ); // this fxn will also bind the material
if ( !pMesh )
return;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nTotalTriCount );
CUtlVector< CRenderGeometry > &renderGeometry = renderList.m_RenderGeometryLists[geometryIndex];
int nGraphicCount = renderGeometry.Count();
int nIndex = 0;
for( int i = 0; i < nGraphicCount; ++i )
{
for ( int j = 0; j < renderGeometry[i].m_Positions.Count(); ++j )
{
// First anim frame
float flX = renderGeometry[i].m_Positions[j].x;
float flY = renderGeometry[i].m_Positions[j].y;
meshBuilder.Position3f( flX, flY, 0.0f );
color32 c = renderGeometry[i].m_VertexColors[j];
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
float texCoordX = renderGeometry[i].m_TextureCoords[j].x;
float texCoordY = renderGeometry[i].m_TextureCoords[j].y;
meshBuilder.TexCoord3f( 0, texCoordX, texCoordY, 0 );
meshBuilder.AdvanceVertex();
}
Assert( renderGeometry[i].m_Positions.Count() == 4 );
// FIXME make this work with generic convex shapes.
// Quads only.
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 1 );
meshBuilder.FastIndex( nIndex + 2 );
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 2 );
meshBuilder.FastIndex( nIndex + 3 );
nIndex += (4);
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Render a font layer in source 1
//-----------------------------------------------------------------------------
void CGameUISystem::RenderTextLayer( CUtlVector< CRenderGeometry > &renderGeometry )
{
if ( renderGeometry.Count() == 0 )
return;
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
// get the character texture from the cache
IMaterial *pMaterial = g_pGameUISystemSurface->GetMaterial( renderGeometry[0].m_FontTextureID ); /// Everything in a text rendering layer uses the same font texture, and the texture id is in the seq #
IMesh* pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial ); // this fxn will also bind the material
if ( !pMesh )
return;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, renderGeometry.Count() );
for ( int i = 0; i < renderGeometry.Count(); ++i )
{
Assert( renderGeometry[i].m_Positions.Count() == 4 );
for ( int j = 0; j < renderGeometry[i].m_Positions.Count(); ++j )
{
meshBuilder.Position3f( renderGeometry[i].m_Positions[j].x, renderGeometry[i].m_Positions[j].y, 0.0f );
meshBuilder.Color4ub( renderGeometry[i].m_VertexColors[j].r, renderGeometry[i].m_VertexColors[j].g, renderGeometry[i].m_VertexColors[j].b, renderGeometry[i].m_VertexColors[j].a );
meshBuilder.TexCoord3f( 0, renderGeometry[i].m_TextureCoords[j].x, renderGeometry[i].m_TextureCoords[j].y, 0 );
meshBuilder.AdvanceVertex();
}
}
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Create geometry mesh in source 1
//-----------------------------------------------------------------------------
void CGameUISystem::GenerateUIMesh( IMatRenderContext *pRenderContext,
IMesh* pMesh,
CUtlVector< CRenderGeometry > &renderGeometry,
CSheet *pSheet )
{
int nTotalTriCount = 0;
for( int i = 0; i < renderGeometry.Count(); ++i )
{
nTotalTriCount += renderGeometry[i].GetTriangleCount();
}
Assert( nTotalTriCount != 0 );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_TRIANGLES, nTotalTriCount * 2 );
int x, y, width, height;
pRenderContext->GetViewport( x, y, width, height);
static long flAge = 0;
{
VPROF_BUDGET( "meshBuilder", "meshBuilder" );
int nGraphicCount = renderGeometry.Count();
int nIndex = 0;
for( int i = 0; i < nGraphicCount; ++i )
{
const SheetSequenceSample_t *pSample = NULL;
int seqNum = renderGeometry[i].m_SheetSequenceNumber;
if ( renderGeometry[i].m_bAnimate )
{
DmeTime_t flStartTime = renderGeometry[i].GetAnimStartTime();
DmeTime_t flAgeInSeconds = ( g_pGameUISystemMgrImpl->GetTime() - flStartTime );
float m_flAnimationRate = renderGeometry[i].m_AnimationRate;
float flAgeScale = m_flAnimationRate * SEQUENCE_SAMPLE_COUNT;
flAgeScale /= pSheet->m_SheetInfo[seqNum].m_flFrameSpan;
pSample = pSheet->GetSampleForSequence( flAgeInSeconds.GetSeconds(), flAgeScale, seqNum, true );
}
else
{
pSample = pSheet->m_SheetInfo[seqNum].m_pSamples;
}
Assert( pSample );
const SequenceSampleTextureCoords_t *pSample0 = &(pSample->m_TextureCoordData[0]);
Assert( pSample0 );
for ( int j = 0; j < renderGeometry[i].m_Positions.Count(); ++j )
{
// First anim frame
float flX = renderGeometry[i].m_Positions[j].x;
float flY = renderGeometry[i].m_Positions[j].y;
meshBuilder.Position3f( flX, flY, 0.0f );
color32 c = renderGeometry[i].m_VertexColors[j];
c.a *= ( 1 - pSample->m_fBlendFactor );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
float sampleWidth = pSample0->m_fRight_U0 - pSample0->m_fLeft_U0;
float sampleHeight = pSample0->m_fBottom_V0 - pSample0->m_fTop_V0;
float texCoordX = pSample0->m_fLeft_U0 + renderGeometry[i].m_TextureCoords[j].x * sampleWidth;
float texCoordY = pSample0->m_fTop_V0 + renderGeometry[i].m_TextureCoords[j].y * sampleHeight;
meshBuilder.TexCoord3f( 0, texCoordX, texCoordY, 0 );
meshBuilder.AdvanceVertex();
// Ugh, right now we have to do this second frame because of the total triangle count being set before we figure out if we need it.
// Second anim frame
//if ( pSample->m_fBlendFactor < 1.0 )
{
meshBuilder.Position3f( flX, flY, 0.0f );
c = renderGeometry[i].m_VertexColors[j];
c.a *= ( pSample->m_fBlendFactor );
meshBuilder.Color4ub( c.r, c.g, c.b, c.a );
float texCoordX = pSample0->m_fLeft_U1 + renderGeometry[i].m_TextureCoords[j].x * sampleWidth;
float texCoordY = pSample0->m_fTop_V1 + renderGeometry[i].m_TextureCoords[j].y * sampleHeight;
meshBuilder.TexCoord3f( 0, texCoordX, texCoordY, 0 );
meshBuilder.AdvanceVertex();
}
}
//if ( pSample->m_fBlendFactor < 1.0 )
{
// FIME make this work with generic convex shapes.
// Quads only.
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 2 );
meshBuilder.FastIndex( nIndex + 4 );
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 4 );
meshBuilder.FastIndex( nIndex + 6 );
meshBuilder.FastIndex( nIndex + 1 );
meshBuilder.FastIndex( nIndex + 3 );
meshBuilder.FastIndex( nIndex + 5 );
meshBuilder.FastIndex( nIndex + 1 );
meshBuilder.FastIndex( nIndex + 5 );
meshBuilder.FastIndex( nIndex + 7 );
nIndex += (4 * 2);
}
/*
else
{
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 1 );
meshBuilder.FastIndex( nIndex + 2 );
meshBuilder.FastIndex( nIndex );
meshBuilder.FastIndex( nIndex + 2 );
meshBuilder.FastIndex( nIndex + 3 );
nIndex += (4 * 1);
}
*/
}
}
meshBuilder.End();
}
//-----------------------------------------------------------------------------
// 3 draw calls per layer.
// Render the UI in source 2
//-----------------------------------------------------------------------------
void CGameUISystem::Render( IRenderContext *pRenderContext, const Rect_t &viewport )
{
if ( !m_GameUIDef.GetVisible() )
return;
m_GameUIDef.UpdateGeometry();
m_GameUIDef.UpdateRenderTransforms( viewport );
CUtlVector< LayerRenderLists_t > renderLists;
m_GameUIDef.GetRenderData( renderLists );
// Note this is not scaling correctly!
pRenderContext->SetCullMode( RENDER_CULLMODE_CULL_NONE );
pRenderContext->SetBlendMode( RENDER_BLEND_ALPHABLENDING );
pRenderContext->BindVertexShader( g_pGameUISystemMgrImpl->m_hVertexShader, g_pGameUISystemMgrImpl->m_hInputLayout );
pRenderContext->BindShader( RENDER_PIXEL_SHADER, g_pGameUISystemMgrImpl->m_hPixelShader );
float pViewportInfo[4] = { viewport.x + 0.5f, viewport.y + 0.5f, viewport.width, viewport.height };
pRenderContext->SetConstantBufferData( g_pGameUISystemMgrImpl->m_hConstBuffer, pViewportInfo, 4 * sizeof( float ) );
pRenderContext->BindConstantBuffer( RENDER_VERTEX_SHADER, g_pGameUISystemMgrImpl->m_hConstBuffer, 0, 0 );
int nLists = renderLists.Count();
for ( int i = 0; i < nLists; ++i )
{
if ( renderLists[i].m_LayerType == SUBLAYER_STATIC )
{
for ( int j = 0; j < renderLists[i].m_RenderGeometryLists.Count(); ++j )
{
RenderStaticLayer( pRenderContext, renderLists[i], j );
}
}
else if ( renderLists[i].m_LayerType == SUBLAYER_FONT )
{
for ( int j = 0; j < renderLists[i].m_RenderGeometryLists.Count(); ++j )
{
RenderTextLayer( pRenderContext, renderLists[i].m_RenderGeometryLists[j] );
}
}
}
}
//-----------------------------------------------------------------------------
// Render a font layer in source 2
//-----------------------------------------------------------------------------
void CGameUISystem::RenderTextLayer( IRenderContext *pRenderContext, CUtlVector< CRenderGeometry > &renderGeometry )
{
if ( renderGeometry.Count() == 0 )
return;
// get the character texture from the cache
HRenderTexture fontTextureHandle = g_pGameUISystemSurface->GetTextureHandle( renderGeometry[0].m_FontTextureID );
pRenderContext->BindTexture( 0, fontTextureHandle );
CDynamicVertexData< GameUIVertex_t > vb( pRenderContext, renderGeometry.Count() * 4, "gamelayer", "game_controls" );
vb.Lock();
for ( int i = 0; i < renderGeometry.Count(); ++i )
{
Assert( renderGeometry[i].m_Positions.Count() == 4 );
for ( int j = 0; j < renderGeometry[i].m_Positions.Count(); ++j )
{
vb->m_vecPosition.Init( renderGeometry[i].m_Positions[j].x, renderGeometry[i].m_Positions[j].y, 0.0f );
vb->m_color = renderGeometry[i].m_VertexColors[j];
vb->m_vecTexCoord.Init( renderGeometry[i].m_TextureCoords[j].x, renderGeometry[i].m_TextureCoords[j].y );
vb.AdvanceVertex();
}
}
vb.Unlock();
vb.Bind( 0, 0 );
CDynamicIndexData< uint16 > ib( pRenderContext, renderGeometry.Count() * 6, "gamelayer", "game_controls" );
ib.Lock();
int nIndex = 0;
for( int i = 0; i < renderGeometry.Count(); ++i )
{
ib.Index( nIndex );
ib.Index( nIndex + 1 );
ib.Index( nIndex + 2 );
ib.Index( nIndex );
ib.Index( nIndex + 2 );
ib.Index( nIndex + 3 );
nIndex += 4;
}
ib.Unlock();
ib.Bind( 0 );
pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, renderGeometry.Count() * 6 );
// For debugging.
//int x = 300;
//int y = 300;
//g_pGameUISystemSurface->DrawFontTexture( pRenderContext, renderGeometry[0].m_FontTextureID, x, y );
//x += 256;
}
//-----------------------------------------------------------------------------
// Renders the static layer in source 2
//-----------------------------------------------------------------------------
void CGameUISystem::RenderStaticLayer( IRenderContext *pRenderContext, LayerRenderLists_t &renderList, int geometryIndex )
{
int nGraphicCount = renderList.m_RenderGeometryLists[geometryIndex].Count();
if ( !nGraphicCount )
return;
int nTotalIndexCount = 0;
int nTotalVertexCount = 0;
int nGeometryCount = renderList.m_RenderGeometryLists[geometryIndex].Count();
for( int i = 0; i < nGeometryCount; ++i )
{
nTotalIndexCount += renderList.m_RenderGeometryLists[geometryIndex][i].GetTriangleCount() * 3;
nTotalVertexCount += renderList.m_RenderGeometryLists[geometryIndex][i].GetVertexCount();
}
if ( nTotalIndexCount == 0 )
return;
pRenderContext->BindTexture( 0, renderList.m_hTexture );
CDynamicVertexData< GameUIVertex_t > vb( pRenderContext, nTotalVertexCount * 2, "gamelayer", "game_controls" );
vb.Lock();
for( int i = 0; i < nGeometryCount; ++i )
{
CRenderGeometry *pGeometry = &renderList.m_RenderGeometryLists[geometryIndex][i];
const SheetSequenceSample_t *pSample = NULL;
int seqNum = pGeometry->m_SheetSequenceNumber;
if ( pGeometry->m_bAnimate )
{
DmeTime_t flStartTime = pGeometry->GetAnimStartTime();
DmeTime_t flAgeInSeconds = ( g_pGameUISystemMgrImpl->GetTime() - flStartTime );
float m_flAnimationRate = pGeometry->m_AnimationRate;
float flAgeScale = m_flAnimationRate * SEQUENCE_SAMPLE_COUNT;
flAgeScale /= renderList.m_pSheet->m_SheetInfo[seqNum].m_flFrameSpan;
pSample = renderList.m_pSheet->GetSampleForSequence( flAgeInSeconds.GetSeconds(), flAgeScale, seqNum, true );
}
else
{
pSample = renderList.m_pSheet->m_SheetInfo[seqNum].m_pSamples;
}
Assert( pSample );
const SequenceSampleTextureCoords_t *pSample0 = &(pSample->m_TextureCoordData[0]);
Assert( pSample0 );
for ( int j = 0; j < pGeometry->m_Positions.Count(); ++j )
{
// First anim frame
float flX = pGeometry->m_Positions[j].x;
float flY = pGeometry->m_Positions[j].y;
vb->m_vecPosition.Init( flX, flY, 0.0f );
color32 c = pGeometry->m_VertexColors[j];
c.a *= ( 1 - pSample->m_fBlendFactor );
vb->m_color = c;
float sampleWidth = pSample0->m_fRight_U0 - pSample0->m_fLeft_U0;
float sampleHeight = pSample0->m_fBottom_V0 - pSample0->m_fTop_V0;
float texCoordX = pSample0->m_fLeft_U0 + pGeometry->m_TextureCoords[j].x * sampleWidth;
float texCoordY = pSample0->m_fTop_V0 + pGeometry->m_TextureCoords[j].y * sampleHeight;
vb->m_vecTexCoord.Init( texCoordX, texCoordY );
vb.AdvanceVertex();
// Second anim frame
//if ( pSample->m_fBlendFactor < 1.0 )
{
c = pGeometry->m_VertexColors[j];
c.a *= ( pSample->m_fBlendFactor );
vb->m_color = c;
float texCoordX = pSample0->m_fLeft_U1 + pGeometry->m_TextureCoords[j].x * sampleWidth;
float texCoordY = pSample0->m_fTop_V1 + pGeometry->m_TextureCoords[j].y * sampleHeight;
vb->m_vecTexCoord.Init( texCoordX, texCoordY );
vb.AdvanceVertex();
}
}
}
vb.Unlock();
vb.Bind( 0, 0 );
CDynamicIndexData< uint16 > ib( pRenderContext, nTotalIndexCount * 2, "gamelayer", "game_controls" );
ib.Lock();
int nIndex = 0;
for( int i = 0; i < nGeometryCount; ++i )
{
ib.Index( nIndex );
ib.Index( nIndex + 2 );
ib.Index( nIndex + 4 );
ib.Index( nIndex );
ib.Index( nIndex + 4 );
ib.Index( nIndex + 6 );
ib.Index( nIndex + 1 );
ib.Index( nIndex + 3 );
ib.Index( nIndex + 5 );
ib.Index( nIndex + 1 );
ib.Index( nIndex + 5 );
ib.Index( nIndex + 7 );
nIndex += (4 * 2);
/*
// FIXME: Deal with sometimes only rendering 1 triangle above
CGeometry *pGeometry = geometry[i];
int nTriangleCount = pGeometry->m_Triangles.Count();
for ( int j = 0; j < nTriangleCount; ++j )
{
CTriangle *pTriangle = &pGeometry->m_Triangles[j];
//if ( pSample->m_fBlendFactor < 1.0 )
{
ib.Index( nIndex + pTriangle->m_PointIndex[0] * 2 );
ib.Index( nIndex + pTriangle->m_PointIndex[1] * 2 );
ib.Index( nIndex + pTriangle->m_PointIndex[2] * 2 );
ib.Index( nIndex + pTriangle->m_PointIndex[0] * 2 + 1 );
ib.Index( nIndex + pTriangle->m_PointIndex[1] * 2 + 1 );
ib.Index( nIndex + pTriangle->m_PointIndex[2] * 2 + 1 );
}
else
{
//ib.Index( nIndex + pTriangle->m_PointIndex[0] );
//ib.Index( nIndex + pTriangle->m_PointIndex[1] );
//ib.Index( nIndex + pTriangle->m_PointIndex[2] );
//nIndex += 3;
}
}
nIndex += (3 * 2) * nTriangleCount;
*/
}
ib.Unlock();
ib.Bind( 0 );
pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, nTotalIndexCount * 2 );
}

View File

@@ -0,0 +1,154 @@
// ----------------------------------------- //
// File generated by VPC //
// ----------------------------------------- //
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\animdata.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\animdata.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\animdata.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Debug output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Release output file: F:\csgo_64\cstrike15_src\common\debug_lib_check.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\dynamicrect.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\dynamicrect.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\dynamicrect.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamegraphic.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamegraphic.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamegraphic.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameLayer.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameLayer.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameLayer.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamerect.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamerect.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamerect.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamestage.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamestage.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gamestage.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gametext.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gametext.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gametext.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidefinition.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidefinition.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidefinition.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidynamictextures.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidynamictextures.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuidynamictextures.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuischeme.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuischeme.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuischeme.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameUISystem.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameUISystem.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\GameUISystem.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemmgr.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemmgr.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemmgr.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemsurface.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemsurface.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuisystemsurface.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicgroup.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicgroup.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicgroup.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\hitarea.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\hitarea.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\hitarea.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\inputgameui.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\inputgameui.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\inputgameui.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\keyrepeat.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\keyrepeat.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\keyrepeat.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\textdisplay.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\textdisplay.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\textdisplay.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\typedlog.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\typedlog.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\typedlog.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\uigeometry.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\uigeometry.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\uigeometry.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscript.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscript.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscript.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptinterface.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptinterface.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptinterface.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptsystem.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptsystem.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\gameuiscriptsystem.cpp
Containing unity file:
PCH file:
Source file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicscriptinterface.cpp
Debug output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicscriptinterface.cpp
Release output file: F:\csgo_64\cstrike15_src\vgui2\game_controls\graphicscriptinterface.cpp
Containing unity file:
PCH file:

View File

@@ -0,0 +1,126 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "animdata.h"
#include "dmxloader/dmxelement.h"
//#include "tier1/utlvector.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_DMXELEMENT_UNPACK ( CAnimData )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pStateName )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "animalias", "", m_pAnimAlias )
DMXELEMENT_UNPACK_FIELD( "textureanimsequencesheetnumber", "0", int, m_TextureAnimSheetSeqNumber )
DMXELEMENT_UNPACK_FIELD( "animationrate", "1", float, m_AnimationRate )
END_DMXELEMENT_UNPACK( CAnimData, s_AnimDataUnpack )
//-----------------------------------------------------------------------------
// Constructor, Destructor
//-----------------------------------------------------------------------------
CAnimData::CAnimData( )
{
m_pStateName = "";
m_pAnimAlias = "";
m_TextureAnimSheetSeqNumber = 0;
m_AnimationRate = 1.0;
}
CAnimData::~CAnimData( )
{
}
//-----------------------------------------------------------------------------
// Populate with data from file.
//-----------------------------------------------------------------------------
bool CAnimData::Unserialize( CDmxElement *pElement )
{
pElement->UnpackIntoStructure( this, s_AnimDataUnpack );
CDmxAttribute *pAnimAttr = pElement->GetAttribute( "colorlog" );
if ( pAnimAttr )
{
CDmxElement *pAnim = pAnimAttr->GetValue< CDmxElement * >();
if ( !m_ColorAnim.Unserialize( pAnim ))
return false;
}
pAnimAttr = pElement->GetAttribute( "centerlog" );
if ( pAnimAttr )
{
CDmxElement *pAnim = pAnimAttr->GetValue< CDmxElement * >();
if ( !m_CenterPosAnim.Unserialize( pAnim ) )
return false;
}
pAnimAttr = pElement->GetAttribute( "scalelog" );
if ( pAnimAttr )
{
CDmxElement *pAnim = pAnimAttr->GetValue< CDmxElement * >();
if ( !m_ScaleAnim.Unserialize( pAnim ) )
return false;
}
pAnimAttr = pElement->GetAttribute( "rotationlog" );
if ( pAnimAttr )
{
CDmxElement *pAnim = pAnimAttr->GetValue< CDmxElement * >();
if ( !m_RotationAnim.Unserialize( pAnim ) )
return false;
}
pAnimAttr = pElement->GetAttribute( "fontlog" );
if ( pAnimAttr )
{
CDmxElement *pAnim = pAnimAttr->GetValue< CDmxElement * >();
if ( !m_FontAnim.Unserialize( pAnim ) )
return false;
}
return true;
}
//-----------------------------------------------------------------------------
// Return true if this anim is done playing.
//-----------------------------------------------------------------------------
bool CAnimData::IsDone( DmeTime_t time )
{
if ( m_ColorAnim.IsDone( time ) &&
m_CenterPosAnim.IsDone( time ) &&
m_ScaleAnim.IsDone( time ) &&
m_RotationAnim.IsDone( time ) &&
m_FontAnim.IsDone( time ) )
{
return true;
}
return false;
}

View File

@@ -0,0 +1,46 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef ANIMDATA_H
#define ANIMDATA_H
#ifdef _WIN32
#pragma once
#endif
#include "typedlog.h"
#include "tier1/utlstring.h"
#include "dmxloader/dmxelement.h"
class CAnimData
{
DECLARE_DMXELEMENT_UNPACK()
public:
CAnimData();
~CAnimData();
bool Unserialize( CDmxElement *pElement );
bool IsDone( DmeTime_t time );
CUtlString m_pStateName;
CUtlString m_pAnimAlias;
int m_TextureAnimSheetSeqNumber;
float m_AnimationRate;
CTypedLog< color32 > m_ColorAnim;
CTypedLog< Vector2D > m_CenterPosAnim;
CTypedLog< Vector2D > m_ScaleAnim;
CTypedLog< float > m_RotationAnim;
CTypedLog< CUtlString > m_FontAnim;
};
#endif // ANIMDATA_H

View File

@@ -0,0 +1,174 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "dynamicrect.h"
// To handle scaling
#include "materialsystem/imaterialsystem.h"
#include "animdata.h"
#include "Color.h"
#include "gameuisystemmgr.h"
#include "gameuidefinition.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Class factory for scripting.
class CDynamicRectClassFactory : IGameUIGraphicClassFactory
{
public:
CDynamicRectClassFactory()
{
Assert( g_pGameUISystemMgrImpl );
g_pGameUISystemMgrImpl->RegisterGraphicClassFactory( "rect", this );
}
// Returns an instance of a graphic interface (keyvalues owned by caller)
virtual CGameGraphic *CreateNewGraphicClass( KeyValues *kvRequest, CGameUIDefinition *pMenu )
{
Assert( pMenu );
CDynamicRect *pNewGraphic = NULL;
const char *pName = kvRequest->GetString( "name", NULL );
if ( pName )
{
pNewGraphic = new CDynamicRect( pName );
// Rects are normally 0,0, doing this so we can see script created rects.
pNewGraphic->SetScale( 100, 100 );
pMenu->AddGraphicToLayer( pNewGraphic, SUBLAYER_DYNAMIC );
// Now set the attributes.
for ( KeyValues *arg = kvRequest->GetFirstSubKey(); arg != NULL; arg = arg->GetNextKey() )
{
pNewGraphic->HandleScriptCommand( arg );
}
}
return pNewGraphic;
}
};
static CDynamicRectClassFactory g_CDynamicRectClassFactory;
BEGIN_DMXELEMENT_UNPACK ( CDynamicRect )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "imagealias", "", m_ImageAlias )
END_DMXELEMENT_UNPACK( CDynamicRect, s_GameDynamicRectUnpack )
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CDynamicRect::CDynamicRect( const char *pName ) : CGameRect( pName )
{
// The default maps to white pixel.
m_ImageAlias = "defaultImageAlias";
}
CDynamicRect::~CDynamicRect()
{
g_pGameUISystemMgrImpl->ReleaseImageAlias( m_ImageAlias );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CDynamicRect::Unserialize( CDmxElement *pGraphic )
{
CGameRect::Unserialize( pGraphic );
pGraphic->UnpackIntoStructure( this, s_GameDynamicRectUnpack );
m_CurrentState = -1;
g_pGameUISystemMgrImpl->InitImageAlias( m_ImageAlias );
g_pGameUISystemMgrImpl->LoadImageAliasTexture( m_ImageAlias, "vguiedit/pixel" );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CDynamicRect::UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
if ( !m_Geometry.m_bVisible )
return;
m_Geometry.SetResultantColor( parentColor );
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
// Now transform our array of positions into local graphic coord system.
int nCount = m_Geometry.m_RelativePositions.Count();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_Geometry.m_RelativePositions[i].x, m_Geometry.m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenpos );
renderGeometry.m_Positions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );;
// TexCoord
Vector2D sheetTexCoords;
g_pGameUISystemMgrImpl->TexCoordsToSheetTexCoords( m_ImageAlias, m_Geometry.m_TextureCoords[i], sheetTexCoords );
renderGeometry.m_TextureCoords.AddToTail( sheetTexCoords );
// Vertex Color
renderGeometry.m_VertexColors.AddToTail( m_Geometry.m_VertexColors[i] );
}
// Triangles
nCount = m_Geometry.m_Triangles.Count();
for ( int i = 0; i < nCount; ++i )
{
renderGeometry.m_Triangles.AddToTail( m_Geometry.m_Triangles[i] );
}
// Anim Info
renderGeometry.m_SheetSequenceNumber = m_Geometry.m_SheetSequenceNumber;
renderGeometry.m_AnimationRate = m_Geometry.m_AnimationRate;
renderGeometry.m_bAnimate = m_Geometry.m_bAnimate;
renderGeometry.m_AnimStartTime = m_Geometry.m_AnimStartTime;
// Set the image alias. This is so we can adjust texture coords if needed if
// This rect's texture gets placed in a sheet.
renderGeometry.m_pImageAlias = m_ImageAlias;
// Now transform our array of positions into local graphic coord system.
nCount = m_Geometry.m_RelativePositions.Count();
m_ScreenPositions.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_Geometry.m_RelativePositions[i].x, m_Geometry.m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenpos );
m_ScreenPositions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );
}
}
KeyValues *CDynamicRect::HandleScriptCommand( KeyValues *args )
{
char const *szCommand = args->GetName();
if ( !Q_stricmp( "SetAlias", szCommand ) )
{
g_pGameUISystemMgrImpl->ReleaseImageAlias( m_ImageAlias );
m_ImageAlias = args->GetString( "alias", "defaultImageAlias" );
g_pGameUISystemMgrImpl->InitImageAlias( m_ImageAlias );
return NULL;
}
return CGameRect::HandleScriptCommand( args );
}

View File

@@ -0,0 +1,51 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef DYNAMICRECT_H
#define DYNAMICRECT_H
#ifdef _WIN32
#pragma once
#endif
#include "gamerect.h"
#include "dmxloader/dmxelement.h"
#include "tier1/utlvector.h"
#include "tier1/keyvalues.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CDynamicRect : public CGameRect
{
DECLARE_DMXELEMENT_UNPACK()
public:
CDynamicRect( const char *pName );
virtual ~CDynamicRect();
bool Unserialize( CDmxElement *pGraphic );
virtual void UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual KeyValues *HandleScriptCommand( KeyValues *args );
virtual bool IsDynamic() const { return true; }
virtual const char *GetMaterialAlias(){ return m_ImageAlias; }
protected:
CDynamicRect();
CUtlString m_ImageAlias;
};
#endif // DYNAMICRECT_H

View File

@@ -0,0 +1,97 @@
//-----------------------------------------------------------------------------
// GAME_CONTROLS.VPC
//
// Project Script
//-----------------------------------------------------------------------------
$macro SRCDIR "..\.."
$include "$SRCDIR\vpc_scripts\source_lib_base.vpc"
$Configuration
{
$Compiler
{
$AdditionalIncludeDirectories "$BASE;$SRCDIR\public\game_controls;$SRCDIR\common\game_controls"
$PreprocessorDefinitions "$BASE;GAMECONTROLS_LIB"
$PrecompiledHeaderFile "Debug/game_controls.pch"
}
}
$Project "game_controls"
{
$Folder "Source Files"
{
$File "animdata.cpp"
$File "dynamicrect.cpp"
$File "gamegraphic.cpp"
$File "gametext.cpp"
$File "GameLayer.cpp"
$File "gamerect.cpp"
$File "gamestage.cpp"
$File "gameuidefinition.cpp"
$File "gameuidynamictextures.cpp"
$File "gameuischeme.cpp"
$File "GameUISystem.cpp"
$File "gameuisystemmgr.cpp"
$File "gameuisystemsurface.cpp"
$File "graphicgroup.cpp"
$File "hitarea.cpp"
$File "inputgameui.cpp"
$File "keyrepeat.cpp"
$File "textdisplay.cpp"
$File "typedlog.cpp"
$File "uigeometry.cpp"
$Folder "Scripting Source Files"
{
$File "gameuiscriptsystem.cpp"
$File "gameuiscriptinterface.cpp"
$File "gameuiscript.cpp"
$File "graphicscriptinterface.cpp"
}
}
$Folder "Header Files"
{
$File "animdata.h"
$File "dynamicrect.h"
$File "gametext.h"
$File "gamelayer.h"
$File "gamerect.h"
$File "gamestage.h"
$File "gameuidefinition.h"
$File "gameuidynamictextures.h"
$File "gameuischeme.h"
$File "gameuisystem.h"
$File "gameuisystemmgr.h"
$File "gameuisystemsurface.h"
$File "graphicgroup.h"
$File "hitarea.h"
$File "inputgameui.h"
$File "gamegraphic.h"
$File "keyrepeat.h"
$File "$SRCDIR\common\game_controls\textdisplay.h"
$File "typedlog.h"
$File "uigeometry.h"
$Folder "Scripting Header Files"
{
$File "gameuiscriptsystem.h"
$File "gameuiscriptinterface.h"
$File "gameuiscript.h"
$File "graphicscriptinterface.h"
}
}
$Folder "Public Header Files"
{
$File "$SRCDIR\public\game_controls\igameuisystemmgr.h"
$File "$SRCDIR\common\game_controls\textdisplay.h"
$File "$SRCDIR\public\tier1\utlmemory.h"
$File "$SRCDIR\public\tier1\utlrbtree.h"
$File "$SRCDIR\public\tier1\utlvector.h"
}
}

View File

@@ -0,0 +1,13 @@
"vpc_cache"
{
"CacheVersion" "1"
"win32"
{
"CRCFile" "game_controls.vcxproj.vpc_crc"
"OutputFiles"
{
"0" "game_controls.vcxproj"
"1" "game_controls.vcxproj.filters"
}
}
}

View File

@@ -0,0 +1,321 @@
//========= Copyright <20> Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "gamegraphic.h"
#include "animdata.h"
#include "gameuisystemmgr.h"
#include "inputgameui.h"
#include "dmxloader/dmxelement.h"
#include "tier1/fmtstr.h"
#include "graphicgroup.h"
#include "gameuiscript.h"
// A list of script handles exposed by the system
static int32 g_iSerialHandle = 0x01000000;
static CUtlMap< int32, CGameGraphic * > g_mapScriptHandles( DefLessFunc( int32 ) );
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CGameGraphic::CGameGraphic() :
m_iScriptHandle( ++g_iSerialHandle )
{
g_mapScriptHandles.InsertOrReplace( m_iScriptHandle, this );
m_pName = "";
m_pGroup = NULL;
m_bCanAcceptInput = false;
m_CurrentState = -1;
m_flAnimTime = DMETIME_ZERO;
}
CGameGraphic::~CGameGraphic()
{
if ( m_pGroup )
{
m_pGroup->RemoveFromGroup( this );
}
int nCount = m_Anims.Count();
for ( int i = 0; i < nCount; ++i )
{
delete m_Anims[i];
m_Anims[i] = NULL;
}
m_Anims.RemoveAll();
g_mapScriptHandles.Remove( m_iScriptHandle );
}
CGameGraphic * CGameGraphic::FromScriptHandle( int32 iScriptHandle )
{
unsigned short usIdx = g_mapScriptHandles.Find( iScriptHandle );
return ( usIdx == g_mapScriptHandles.InvalidIndex() ) ? NULL : g_mapScriptHandles.Element( usIdx );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
DmeTime_t CGameGraphic::GetAnimationTimePassed()
{
if ( m_Geometry.m_bAnimate )
{
m_flAnimTime = g_pGameUISystemMgrImpl->GetTime() - m_Geometry.m_AnimStartTime;
}
return m_flAnimTime;
}
KeyValues * CGameGraphic::HandleScriptCommand( KeyValues *args )
{
char const *szCommand = args->GetName();
if ( !Q_stricmp( "SetCenter", szCommand ) )
{
SetCenter( args->GetFloat( "x" ), args->GetFloat( "y" ) );
return NULL;
}
else if ( !Q_stricmp( "SetScale", szCommand ) )
{
SetScale( args->GetFloat( "x" ), args->GetFloat( "y" ) );
return NULL;
}
else if ( !Q_stricmp( "SetRotation", szCommand ) )
{
m_Geometry.m_Rotation = args->GetFloat( "rotation", 0.0f );
return NULL;
}
else if ( !Q_stricmp( "SetVisible", szCommand ) )
{
SetVisible( args->GetBool( "visible", true ) );
return NULL;
}
else if ( !Q_stricmp( "GetVisible", szCommand ) )
{
return new KeyValues( "", "visible", GetVisible() ? 1 : 0 );
}
else if ( !Q_stricmp( "SetHorizGradient", szCommand ) )
{
m_Geometry.m_bHorizontalGradient = args->GetBool( "horizgradient", true );
return NULL;
}
else if ( !Q_stricmp( "SetColor", szCommand ) )
{
Color c = args->GetColor( "color", Color( 255, 255, 255, 255 ) );
color32 color;
color.r = c[0];
color.g = c[1];
color.b = c[2];
color.a = c[3];
SetColor( color );
return NULL;
}
else if ( !Q_stricmp( "SetState", szCommand ) )
{
SetState( args->GetString( "state" ), args->GetBool( "play", true ) );
SetAnimationTimePassed( DmeTime_t( args->GetFloat( "time" ) ) );
return NULL;
}
else if ( !Q_stricmp( "GetState", szCommand ) )
{
return new KeyValues( "", "state", GetState() );
}
else if ( !Q_stricmp( "IsDonePlaying", szCommand ) )
{
return new KeyValues( "", "done", IsDonePlaying() ? 1 : 0 );
}
DevWarning( "CGameGraphic::HandleScriptCommand for unknown command %s!\n", args->GetName() );
return NULL;
}
//-----------------------------------------------------------------------------
// If you don't want to use the clock, you can set the time yourself.
//----------------------------------------------------------------------------
void CGameGraphic::SetAnimationTimePassed( DmeTime_t time )
{
m_flAnimTime = time;
}
//-----------------------------------------------------------------------------
// Populate lists for rendering
//-----------------------------------------------------------------------------
void CGameGraphic::UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
if ( !m_Geometry.m_bVisible )
return;
m_Geometry.SetResultantColor( parentColor );
m_Geometry.UpdateRenderData( renderGeometryLists, firstListIndex );
}
//-----------------------------------------------------------------------------
// Have to do this separately because extents are drawn as rects.
//-----------------------------------------------------------------------------
void CGameGraphic::DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
Assert( !IsGroup() );
color32 extentLineColor = { 0, 255, 0, 255 };
m_Geometry.DrawExtents( renderGeometryLists, firstListIndex, extentLineColor );
}
//-----------------------------------------------------------------------------
// Populate lists for rendering
//-----------------------------------------------------------------------------
void CGameGraphic::UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo )
{
m_Geometry.UpdateRenderTransforms( stageRenderInfo, GetGroup() );
}
//-----------------------------------------------------------------------------
// Return the index of the anim this state name maps to.
//-----------------------------------------------------------------------------
bool CGameGraphic::HasState( const char *pStateName )
{
return (GetStateIndex( pStateName ) != -1);
}
//-----------------------------------------------------------------------------
// Set the animation state of this graphic.
// Default is to start playing it. If it is called with startplaying false, it will stop it.
//-----------------------------------------------------------------------------
void CGameGraphic::SetState( const char *pStateName, bool bStartPlaying )
{
int newState = GetStateIndex( pStateName );
if ( ( newState != -1 ) && ( m_CurrentState != newState ) )
{
m_CurrentState = newState;
if ( bStartPlaying )
{
StartPlaying();
}
}
if ( !bStartPlaying )
{
StopPlaying();
}
}
//-----------------------------------------------------------------------------
// Return true if anim is done playing its current state.
//-----------------------------------------------------------------------------
bool CGameGraphic::IsDonePlaying()
{
if ( m_CurrentState == -1 )
return true;
return m_Anims[m_CurrentState]->IsDone( GetAnimationTimePassed() );
}
//-----------------------------------------------------------------------------
// Return the index of the anim this state name maps to.
//-----------------------------------------------------------------------------
int CGameGraphic::GetStateIndex( const char *pStateName )
{
for ( int i = 0; i < m_Anims.Count(); i++ )
{
if ( Q_stricmp( pStateName, m_Anims[i]->m_pStateName ) == 0 )
{
if ( Q_stricmp( m_Anims[i]->m_pAnimAlias, "" ) != 0 )
{
return GetStateIndex( m_Anims[i]->m_pAnimAlias );
}
else
{
return i;
}
}
}
return -1;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CGameGraphic::GetState()
{
if ( m_CurrentState == -1 )
return "";
if ( Q_stricmp( m_Anims[m_CurrentState]->m_pAnimAlias, "" ) != 0 )
{
return m_Anims[m_CurrentState]->m_pAnimAlias;
}
else
{
return m_Anims[m_CurrentState]->m_pStateName;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameGraphic::StartPlaying()
{
m_Geometry.m_bAnimate = true;
m_Geometry.m_AnimStartTime = g_pGameUISystemMgrImpl->GetTime();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameGraphic::StopPlaying()
{
m_Geometry.m_bAnimate = false;
}
//-----------------------------------------------------------------------------
// for demo and unit tests
//-----------------------------------------------------------------------------
void CGameGraphic::AdvanceState()
{
StopPlaying();
int numStates = m_Anims.Count();
if ( numStates == 0 )
return;
int state = m_CurrentState;
state++;
if ( state > numStates -1 )
state = 0;
m_CurrentState = state;
}
//-----------------------------------------------------------------------------
// Is this the graphic with this name?
//-----------------------------------------------------------------------------
bool CGameGraphic::IsGraphicNamed( const char *pName )
{
if ( !Q_stricmp( m_pName.Get(), pName ) )
{
// Match.
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Does this graphic own a graphic with this name?
//-----------------------------------------------------------------------------
CGameGraphic *CGameGraphic::FindGraphicByName( const char *pName ) const
{
return NULL;
}

View File

@@ -0,0 +1,118 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEGRAPHIC_H
#define GAMEGRAPHIC_H
#ifdef _WIN32
#pragma once
#endif
#include "uigeometry.h"
#include "tier1/utlvector.h"
#include "inputsystem/ButtonCode.h"
#include "tier1/utlstring.h"
//#include "gameuiscript.h"
#include "filesystem.h"
struct InputEvent_t;
class CGraphicGroup;
class CGameUIScript;
class CGameUIDefinition;
class CAnimData;
class CDmxElement;
enum EScriptExecution;
struct StageRenderInfo_t
{
Vector parentPos;
Vector2D parentScale;
int parentRot;
matrix3x4_t relToScreen;
matrix3x4_t relToScreenHoldAspectRatio;
};
//-----------------------------------------------------------------------------
// A class that contains a rect or text or hit area
//-----------------------------------------------------------------------------
class CGameGraphic
{
public:
CGameGraphic();
virtual ~CGameGraphic();
// Update geometry and execute scripting.
virtual void UpdateGeometry(){}
// Populate lists for rendering
virtual void UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo );
virtual void UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual void DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual bool HasState( const char *pStateName );
virtual void SetState( const char *pStateName, bool bStartPlaying = true );
bool IsDonePlaying();
const char *GetState();
virtual void StartPlaying();
virtual void StopPlaying();
virtual void AdvanceState();
void SetAnimationTimePassed( DmeTime_t time );
DmeTime_t GetAnimationTimePassed();
virtual KeyValues *HandleScriptCommand( KeyValues *args );
virtual bool HitTest( int x, int y ) { return false; }
CGraphicGroup *GetGroup() const { return m_pGroup; }
void SetGroup( CGraphicGroup *pGroup ) { m_pGroup = pGroup; }
const char *GetName() const { return m_pName; }
bool IsGraphicNamed( const char *pName );
virtual CGameGraphic *FindGraphicByName( const char *pName ) const;
virtual void SetVisible( bool bVisible ){ m_Geometry.m_bVisible = bVisible; }
bool GetVisible( ) const { return m_Geometry.m_bVisible; }
bool CanAcceptInput() const { return m_bCanAcceptInput; }
virtual bool IsHitArea() const { return false; }
virtual bool IsGroup() const { return false; }
virtual bool IsDynamic() const { return false; }
void SetResultantColor( bool bTop, color32 parentColor );
virtual bool MaintainAspectRatio() const { return m_Geometry.m_bMaintainAspectRatio; }
int32 GetScriptHandle() { return m_iScriptHandle; }
static CGameGraphic * FromScriptHandle( int32 iScriptHandle );
virtual const char *GetMaterialAlias(){ return NULL; }
virtual void SetCenter( float x, float y ) { m_Geometry.m_Center = Vector2D( x, y ); }
virtual void SetScale( float xScale, float yScale ) { m_Geometry.m_Scale = Vector2D( xScale, yScale); }
virtual void SetColor( color32 c ){ m_Geometry.m_Color = c; }
protected:
int GetStateIndex( const char *pStateName );
CUtlString m_pName;
CGraphicGroup *m_pGroup;
bool m_bCanAcceptInput;
CGeometry m_Geometry;
CUtlVector< CAnimData * > m_Anims;
int m_CurrentState;
DmeTime_t m_flAnimTime;
int32 m_iScriptHandle;
};
#endif // GAMEGRAPHIC_H

View File

@@ -0,0 +1,116 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMELAYER_H
#define GAMELAYER_H
#ifdef _WIN32
#pragma once
#endif
#include "igameuisystemmgr.h"
#include "gamegraphic.h"
#include "dmxloader/dmxelement.h"
#include "materialsystem/materialsystemutil.h"
#include "bitmap/psheet.h"
#include "rendersystem/irenderdevice.h"
#include "mathlib/vertexcolor.h"
#include "resourcesystem/stronghandle.h"
#include "tier1/utldict.h"
#include "tier1/UtlStringMap.h"
class IRenderContext;
struct GameGraphicMap_t;
class CGameGraphic;
class GameUIDefinition;
//-----------------------------------------------------------------------------
// GameUI vertex format
//-----------------------------------------------------------------------------
struct GameUIVertex_t
{
Vector m_vecPosition;
VertexColor_t m_color;
Vector2D m_vecTexCoord;
};
//-----------------------------------------------------------------------------
// A class that contains all of the rendering objects in a gameui layer
//-----------------------------------------------------------------------------
// There are currently 3 types of these, for static/dynamic/and font.
class CGameLayer
{
DECLARE_DMXELEMENT_UNPACK()
public:
CGameLayer( SublayerTypes_t layerType = SUBLAYER_STATIC );
~CGameLayer();
void Shutdown();
bool Unserialize( CDmxElement *pLayer, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping );
const char *GetName() const { return m_pName; }
const SublayerTypes_t GetLayerType() { return m_LayerType; }
void SetLayerType( SublayerTypes_t layerType ) { m_LayerType = layerType; }
bool InitSheetTexture();
bool InitSheetTexture( const char *pBaseTextureName );
void GetSheetTextureSize( int &nWidth, int &nHeight );
int AddGraphic( CGameGraphic *pGraphic );
bool RemoveGraphic( CGameGraphic *pGraphic );
void ClearGraphics();
bool HasGraphic( CGameGraphic *pGraphic );
CGameGraphic *FindGraphicByName( const char *pName );
IMaterial *GetMaterial();
HRenderTextureStrong GetTexture() { return m_hTexture; }
// Sheet symbols (used to avoid string->symbol conversions)
void InvalidateSheetSymbol();
void CacheSheetSymbol( CUtlSymbol sheetSymbol );
bool IsSheetSymbolCached() const { return m_bSheetSymbolCached; }
CUtlSymbol GetSheetSymbol() const;
void StartPlaying();
void StopPlaying();
void AdvanceState();
void InitAnims();
void UpdateGeometry();
void UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo );
void UpdateRenderData( CGameUIDefinition &gameUIDef, color32 parentColor, CUtlVector< LayerRenderLists_t > &renderLists );
CGameGraphic *GetGraphic( int x, int y );
CGameGraphic *GetMouseFocus( int x, int y );
CGameGraphic *GetNextFocus( bool &bGetNext, CGameGraphic *pCurrentGraphic );
private:
// Graphics in this layer
CUtlVector< CGameGraphic * > m_LayerGraphics;
CSheet *LoadSheet( IMaterial *pMaterial );
CSheet *LoadSheet( char const *pszFname, ITexture *pTexture );
CUtlString m_pName;
SublayerTypes_t m_LayerType;
CUtlString m_pTextureName;
HRenderTextureStrong m_hTexture;
CMaterialReference m_Material;
CUtlReference< CSheet > m_Sheet;
CUtlSymbol m_SheetSymbol;
bool m_bSheetSymbolCached;
};
#endif // GAMELAYER_H

View File

@@ -0,0 +1,297 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "gamerect.h"
// To handle scaling
#include "materialsystem/imaterialsystem.h"
#include "animdata.h"
#include "Color.h"
#include "gameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_DMXELEMENT_UNPACK ( CGameRect )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
DMXELEMENT_UNPACK_FIELD( "center", "0 0", Vector2D, m_Geometry.m_Center )
DMXELEMENT_UNPACK_FIELD( "scale", "0 0", Vector2D, m_Geometry.m_Scale )
DMXELEMENT_UNPACK_FIELD( "rotation", "0", float, m_Geometry.m_Rotation )
DMXELEMENT_UNPACK_FIELD( "maintainaspectratio", "0", bool, m_Geometry.m_bMaintainAspectRatio )
DMXELEMENT_UNPACK_FIELD( "sublayertype", "0", int, m_Geometry.m_Sublayer )
DMXELEMENT_UNPACK_FIELD( "visible", "1", bool, m_Geometry.m_bVisible )
DMXELEMENT_UNPACK_FIELD( "initialstate", "-1", int, m_CurrentState )
DMXELEMENT_UNPACK_FIELD( "horizgradient", "0", bool, m_Geometry.m_bHorizontalGradient )
DMXELEMENT_UNPACK_FIELD( "color", "255 255 255 255", Color, m_Geometry.m_Color )
DMXELEMENT_UNPACK_FIELD( "topcolor", "255 255 255 255", Color, m_Geometry.m_TopColor )
DMXELEMENT_UNPACK_FIELD( "bottomcolor", "255 255 255 255", Color, m_Geometry.m_BottomColor )
// color is gotten from log.
// sheet seq number is gotten from log.
END_DMXELEMENT_UNPACK( CGameRect, s_GameRectUnpack )
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CGameRect::CGameRect( const char *pName )
{
m_Geometry.m_SheetSequenceNumber = 0; // FIXME, not updating seq numbers yet.
m_bCanAcceptInput = false;
// DME default values.
m_pName = pName;
m_Geometry.m_Center.x = 0;
m_Geometry.m_Center.y = 0;
m_Geometry.m_Scale.x = 0;
m_Geometry.m_Scale.y = 0;
m_Geometry.m_Rotation = 0;
m_Geometry.m_bMaintainAspectRatio = 0;
m_Geometry.m_Sublayer = 0;
m_Geometry.m_bVisible = true;
m_CurrentState = -1;
m_Geometry.m_bHorizontalGradient = false;
m_Geometry.m_Color.r = 255;
m_Geometry.m_Color.g = 255;
m_Geometry.m_Color.b = 255;
m_Geometry.m_Color.a = 255;
m_Geometry.m_TopColor.r = 255;
m_Geometry.m_TopColor.g = 255;
m_Geometry.m_TopColor.b = 255;
m_Geometry.m_TopColor.a = 255;
m_Geometry.m_BottomColor.r = 255;
m_Geometry.m_BottomColor.g = 255;
m_Geometry.m_BottomColor.b = 255;
m_Geometry.m_BottomColor.a = 255;
m_Geometry.m_RelativePositions.AddToTail( Vector2D( -.5, -.5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( .5, -.5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( .5, .5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( -.5, .5 ) );
m_Geometry.m_TextureCoords.AddToTail( Vector2D( 0.0, 0.0 ) );
m_Geometry.m_TextureCoords.AddToTail( Vector2D( 1.0, 0.0 ) );
m_Geometry.m_TextureCoords.AddToTail( Vector2D( 1.0, 1.0 ) );
m_Geometry.m_TextureCoords.AddToTail( Vector2D( 0.0, 1.0 ) );
SetupVertexColors();
CTriangle triangle;
triangle.m_PointIndex[0] = 0;
triangle.m_PointIndex[1] = 1;
triangle.m_PointIndex[2] = 2;
m_Geometry.m_Triangles.AddToTail( triangle );
triangle.m_PointIndex[0] = 0;
triangle.m_PointIndex[1] = 2;
triangle.m_PointIndex[2] = 3;
m_Geometry.m_Triangles.AddToTail( triangle );
}
CGameRect::~CGameRect()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CGameRect::Unserialize( CDmxElement *pGraphic )
{
pGraphic->UnpackIntoStructure( this, s_GameRectUnpack );
// GEOMETRY
CDmxAttribute *pRelativePositions = pGraphic->GetAttribute( "relativepositions" );
if ( !pRelativePositions || pRelativePositions->GetType() != AT_VECTOR2_ARRAY )
{
return false;
}
const CUtlVector< Vector2D > &relpositions = pRelativePositions->GetArray< Vector2D >( );
int nCount = relpositions.Count();
m_Geometry.m_RelativePositions.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relpositions[i].x, relpositions[i].y ) );
}
CDmxAttribute *pTexCoords = pGraphic->GetAttribute( "texcoords" );
if ( !pTexCoords || pTexCoords->GetType() != AT_VECTOR2_ARRAY )
{
return false;
}
const CUtlVector< Vector2D > &texcoords = pTexCoords->GetArray< Vector2D >( );
nCount = texcoords.Count();
m_Geometry.m_TextureCoords.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
m_Geometry.m_TextureCoords.AddToTail( Vector2D( texcoords[i].x, texcoords[i].y ) );
}
SetupVertexColors();
CDmxAttribute *pTriangles = pGraphic->GetAttribute( "triangles" );
if ( !pTriangles || pTriangles->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &triangles = pTriangles->GetArray< CDmxElement * >( );
nCount = triangles.Count();
m_Geometry.m_Triangles.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pPoints = triangles[i]->GetAttribute( "positionindexes" );
const CUtlVector< int > &points = pPoints->GetArray< int >( );
CTriangle triangle;
triangle.m_PointIndex[0] = points[0];
triangle.m_PointIndex[1] = points[1];
triangle.m_PointIndex[2] = points[2];
m_Geometry.m_Triangles.AddToTail( triangle );
}
// ANIMSTATES
CDmxAttribute *pImageAnims = pGraphic->GetAttribute( "imageanims" );
if ( !pImageAnims || pImageAnims->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &imageanims = pImageAnims->GetArray< CDmxElement * >( );
nCount = imageanims.Count();
for ( int i = 0; i < nCount; ++i )
{
CAnimData *pAnimData = new CAnimData;
if ( !pAnimData->Unserialize( imageanims[i] ) )
{
delete pAnimData;
return false;
}
m_Anims.AddToTail( pAnimData );
}
// Ok the initial state is 0, which is (usually ) default.
// default could be aliased to another state though so if it is fix the initial state here.
// default might also not be the state that is 0 so this sets the graphic's initial
// state to be the default one.
SetState( "default" );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameRect::UpdateGeometry()
{
if ( m_CurrentState == -1 )
return;
Assert( m_CurrentState < m_Anims.Count() );
DmeTime_t flAnimTime = GetAnimationTimePassed();
// Update texture
m_Geometry.m_SheetSequenceNumber = m_Anims[ m_CurrentState ]->m_TextureAnimSheetSeqNumber;
m_Geometry.m_AnimationRate = m_Anims[ m_CurrentState ]->m_AnimationRate;
// Update color
m_Anims[ m_CurrentState ]->m_ColorAnim.GetValue( flAnimTime, &m_Geometry.m_Color );
// Update center location
m_Anims[ m_CurrentState ]->m_CenterPosAnim.GetValue( flAnimTime, &m_Geometry.m_Center );
// Update scale
m_Anims[ m_CurrentState ]->m_ScaleAnim.GetValue( flAnimTime, &m_Geometry.m_Scale );
// Update rotation
m_Anims[ m_CurrentState ]->m_RotationAnim.GetValue( flAnimTime, &m_Geometry.m_Rotation );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameRect::UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
if ( !m_Geometry.m_bVisible )
return;
m_Geometry.SetResultantColor( parentColor );
m_Geometry.UpdateRenderData( renderGeometryLists, firstListIndex );
// Now transform our array of positions into local graphic coord system.
int nCount = m_Geometry.m_RelativePositions.Count();
m_ScreenPositions.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_Geometry.m_RelativePositions[i].x, m_Geometry.m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenpos );
m_ScreenPositions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameRect::SetupVertexColors()
{
m_Geometry.m_VertexColors.RemoveAll();
// Create 4 vertex colors for this rect.
color32 c;
c.r = 255;
c.g = 255;
c.b = 255;
c.a = 255;
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
}
//-----------------------------------------------------------------------------
// Determine if x,y is inside the graphic.
//-----------------------------------------------------------------------------
bool CGameRect::HitTest( int x, int y )
{
if ( !m_Geometry.m_bVisible )
return false;
if ( m_ScreenPositions.Count() == 0 )
return false;
for ( int i = 0; i < m_Geometry.GetTriangleCount(); ++i )
{
if ( PointTriangleHitTest(
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[0] ],
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[1] ],
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[2] ],
Vector2D( x, y ) ) )
{
//Msg( "%d, %d hit\n", x, y );
return true;
}
}
return false;
}

View File

@@ -0,0 +1,56 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMERECT_H
#define GAMERECT_H
#ifdef _WIN32
#pragma once
#endif
#include "gamegraphic.h"
#include "dmxloader/dmxelement.h"
#include "tier1/utlvector.h"
class CAnimData;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CGameRect : public CGameGraphic
{
DECLARE_DMXELEMENT_UNPACK()
public:
CGameRect( const char *pName );
virtual ~CGameRect();
bool Unserialize( CDmxElement *pGraphic );
// Update geometry and execute scripting.
virtual void UpdateGeometry();
virtual void UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual bool HitTest( int x, int y );
protected:
CGameRect();
void SetupVertexColors();
CUtlVector< Vector2D > m_ScreenPositions;
};
#endif // GAMERECT_H

View File

@@ -0,0 +1,206 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "gamestage.h"
// To handle scaling
#include "materialsystem/imaterialsystem.h"
#include "animdata.h"
#include "Color.h"
#include "gameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_DMXELEMENT_UNPACK ( CGameStage )
DMXELEMENT_UNPACK_FIELD( "stagesize", "1024 768", Vector2D, m_StageSize )
DMXELEMENT_UNPACK_FIELD( "fullscreen", "1", bool, m_bFullscreen )
END_DMXELEMENT_UNPACK( CGameStage, s_GameStageUnpack )
//-----------------------------------------------------------------------------
// Constructor, destructor
//-----------------------------------------------------------------------------
CGameStage::CGameStage()
{
m_pName = "stage";
m_CurrentState = -1;
m_StageSize.x = 1024;
m_StageSize.y = 768;
m_bFullscreen = true;
m_Geometry.m_bMaintainAspectRatio = false;
m_StageRenderInfo.parentPos.x = 0;
m_StageRenderInfo.parentPos.y = 0;
m_StageRenderInfo.parentPos.z = 0;
m_StageRenderInfo.parentScale.x = 0;
m_StageRenderInfo.parentScale.y = 0;
m_StageRenderInfo.parentRot = 0;
m_MaintainAspectRatioStageSize.x = 640;
m_MaintainAspectRatioStageSize.y = 480;
}
CGameStage::~CGameStage()
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CGameStage::Unserialize( CDmxElement *pElement, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping )
{
pElement->UnpackIntoStructure( this, s_GameStageUnpack );
if ( !CGraphicGroup::Unserialize( pElement, unserializedGraphicMapping ) )
return false;
// Ok the initial state is 0, which is ( usually ) default.
// default could be aliased to another state though so if it is fix the initial state here.
// default might also not be the state that is 0 so this sets the graphic's initial
// state to be the default one.
SetState( "default" );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameStage::UpdateAspectRatio( const Rect_t &viewport )
{
// First do stage scale.
matrix3x4_t scalemat;
float screenScaleX = (float)(viewport.width) / m_StageSize.x;
float screenScaleY = (float)(viewport.height) / m_StageSize.y;
if ( screenScaleX > screenScaleY )
{
screenScaleX = screenScaleY;
}
else
{
screenScaleY = screenScaleX;
}
m_MaintainAspectRatioStageSize.x = screenScaleX * m_StageSize.x;
m_MaintainAspectRatioStageSize.y = screenScaleY * m_StageSize.y;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameStage::UpdateRenderTransforms( const Rect_t &viewport )
{
// Build the raw stage matrix.
// Move the stage to its position.
matrix3x4_t transmat;
SetIdentityMatrix( transmat );
Vector2D screenPos = Vector2D( viewport.width/2, viewport.height/2 );
screenPos += m_Geometry.m_Center;
m_StageRenderInfo.parentPos = Vector( screenPos.x, screenPos.y, 0 );
PositionMatrix( m_StageRenderInfo.parentPos, transmat);
// First do stage scale.
matrix3x4_t scalemat;
float screenScaleX = (float)(viewport.width) / m_StageSize.x;
float screenScaleY = (float)(viewport.height) / m_StageSize.y;
m_StageRenderInfo.parentScale = Vector2D( screenScaleX, screenScaleY );
m_StageRenderInfo.parentScale *= m_Geometry.m_Scale;
SetScaleMatrix( m_StageRenderInfo.parentScale.x, m_StageRenderInfo.parentScale.y, 1, scalemat );
// Build the stage rotation matrix. Normally this is 0.
matrix3x4_t rotmat;
m_StageRenderInfo.parentRot = m_Geometry.m_Rotation;
MatrixBuildRotationAboutAxis( Vector( 0, 0, 1 ), m_StageRenderInfo.parentRot, rotmat );
// Multiply matrices together in the correct order.
matrix3x4_t temp;
MatrixMultiply( rotmat, scalemat, temp );
matrix3x4_t stageRenderMatrix;
MatrixMultiply( transmat, temp, stageRenderMatrix );
m_StageRenderInfo.relToScreen = stageRenderMatrix;
// Now build another stage matrix that holds the aspect ratio.
// This will scale the size of the graphic while maintaining its aspect ratio.
// Move the graphic to its stage position.
SetIdentityMatrix( transmat );
PositionMatrix( m_StageRenderInfo.parentPos, transmat);
if ( screenScaleX > screenScaleY )
{
screenScaleX = screenScaleY;
}
else
{
screenScaleY = screenScaleX;
}
Vector2D screenScale = Vector2D( screenScaleX, screenScaleY );
screenScale *= m_Geometry.m_Scale;
SetScaleMatrix( screenScale.x, screenScale.y, 1, scalemat );
// Build the stage rotation matrix.
MatrixBuildRotationAboutAxis( Vector( 0, 0, 1 ), m_StageRenderInfo.parentRot, rotmat );
// Multiply matrices together in the correct order.
MatrixMultiply( rotmat, scalemat, temp );
matrix3x4_t stageRenderMatrixHoldAspectRatio;
MatrixMultiply( transmat, temp, stageRenderMatrixHoldAspectRatio );
m_StageRenderInfo.relToScreenHoldAspectRatio = stageRenderMatrixHoldAspectRatio;
// Update all children
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->UpdateRenderTransforms( m_StageRenderInfo );
}
m_ResultantColor = m_Geometry.m_Color;
CGraphicGroup::UpdateRenderData( m_Geometry.m_Color );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameStage::SetStageSize( int nWide, int nTall )
{
m_StageSize.x = nWide;
m_StageSize.y = nTall;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameStage::GetRenderTransform( matrix3x4_t &relToScreen, bool bMaintainAspectRatio ) const
{
if ( bMaintainAspectRatio )
{
relToScreen = m_StageRenderInfo.relToScreenHoldAspectRatio;
}
else
{
relToScreen = m_StageRenderInfo.relToScreen;
}
}

View File

@@ -0,0 +1,64 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMESTAGE_H
#define GAMESTAGE_H
#ifdef _WIN32
#pragma once
#endif
#include "graphicgroup.h"
#include "dmxloader/dmxelement.h"
#include "tier1/utlvector.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CGameStage : public CGraphicGroup
{
DECLARE_DMXELEMENT_UNPACK()
public:
CGameStage();
virtual ~CGameStage();
bool Unserialize( CDmxElement *pElement, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping );
// Update geometry and execute scripting.
virtual void UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup ){}
void UpdateRenderTransforms( const Rect_t &viewport );
virtual void GetRenderTransform( matrix3x4_t &relToScreen, bool bMaintainAspectRatio ) const;
const StageRenderInfo_t &GetRenderInfo() const { return m_StageRenderInfo; }
void UpdateAspectRatio( const Rect_t &viewport );
void SetStageSize( int nWide, int nTall );
void GetStageSize( Vector2D &stageSize ) const { stageSize = m_StageSize; }
void GetMaintainAspectRatioStageSize( Vector2D &stageSize ){ stageSize = m_MaintainAspectRatioStageSize; }
color32 GetStageColor() const { return m_Geometry.m_Color; }
virtual bool IsStageGroup() const { return true; }
private:
Vector2D m_StageSize;
Vector2D m_MaintainAspectRatioStageSize;
bool m_bFullscreen;
StageRenderInfo_t m_StageRenderInfo;
};
#endif // GAMESTAGE_H

View File

@@ -0,0 +1,665 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#include "gametext.h"
#include "vgui/ilocalize.h"
#include "vgui/vgui.h"
#include <ctype.h>
#include "gameuisystemsurface.h"
#include "gameuisystemmgr.h"
#include "gameuischeme.h"
#include "graphicgroup.h"
#include "gameuidefinition.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
// Class factory for scripting.
class CGameTextClassFactory : IGameUIGraphicClassFactory
{
public:
CGameTextClassFactory()
{
Assert( g_pGameUISystemMgrImpl );
g_pGameUISystemMgrImpl->RegisterGraphicClassFactory( "text", this );
}
// Returns an instance of a graphic interface (keyvalues owned by caller)
virtual CGameGraphic *CreateNewGraphicClass( KeyValues *kvRequest, CGameUIDefinition *pMenu )
{
Assert( pMenu );
CGameText *pNewGraphic = NULL;
const char *pName = kvRequest->GetString( "name", NULL );
if ( pName )
{
pNewGraphic = new CGameText( pName );
pMenu->AddGraphicToLayer( pNewGraphic, SUBLAYER_FONT );
// Now set the attributes.
for ( KeyValues *arg = kvRequest->GetFirstSubKey(); arg != NULL; arg = arg->GetNextKey() )
{
pNewGraphic->HandleScriptCommand( arg );
}
}
return pNewGraphic;
}
};
static CGameTextClassFactory g_CGameTextClassFactory;
BEGIN_DMXELEMENT_UNPACK ( CGameText )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
DMXELEMENT_UNPACK_FIELD( "center", "0 0", Vector2D, m_Geometry.m_Center )
DMXELEMENT_UNPACK_FIELD( "scale", "1 1", Vector2D, m_Geometry.m_Scale )
DMXELEMENT_UNPACK_FIELD( "rotation", "0", float, m_Geometry.m_Rotation )
DMXELEMENT_UNPACK_FIELD( "maintainaspectratio", "0", bool, m_Geometry.m_bMaintainAspectRatio )
DMXELEMENT_UNPACK_FIELD( "sublayertype", "0", int, m_Geometry.m_Sublayer )
DMXELEMENT_UNPACK_FIELD( "visible", "1", bool, m_Geometry.m_bVisible )
DMXELEMENT_UNPACK_FIELD( "initialstate", "-1", int, m_CurrentState )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "unlocalizedtext", "NONE", m_CharText )
DMXELEMENT_UNPACK_FIELD( "allcaps", "0", bool, m_bAllCaps )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "fontname", "Default", m_FontName )
DMXELEMENT_UNPACK_FIELD( "justfication", "0", int, m_Justification )
DMXELEMENT_UNPACK_FIELD( "color", "255 255 255 255", Color, m_Geometry.m_Color )
DMXELEMENT_UNPACK_FIELD( "topcolor", "255 255 255 255", Color, m_Geometry.m_TopColor )
DMXELEMENT_UNPACK_FIELD( "bottomcolor", "255 255 255 255", Color, m_Geometry.m_BottomColor )
DMXELEMENT_UNPACK_FIELD( "horizgradient", "0", bool, m_Geometry.m_bHorizontalGradient )
// color is gotten from log.
END_DMXELEMENT_UNPACK( CGameText, s_GameTextUnpack )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameText::CGameText( const char *pName )
{
m_UnicodeText = NULL;
m_TextBufferLen = 0;
m_UnlocalizedTextSymbol = vgui::INVALID_STRING_INDEX;
m_Font = vgui::INVALID_FONT;
m_bCanAcceptInput = false;
// DME default values.
m_pName = pName;
m_Geometry.m_Center.x = 0;
m_Geometry.m_Center.y = 0;
m_Geometry.m_Scale.x = 1;
m_Geometry.m_Scale.y = 1;
m_Geometry.m_Rotation = 0;
m_Geometry.m_bMaintainAspectRatio = 1;
m_Geometry.m_Sublayer = 0;
m_Geometry.m_bVisible = true;
m_CurrentState = -1;
m_CharText = "NONE";
m_bAllCaps = false;
m_FontName = "Default";
m_Justification = JUSTIFICATION_LEFT;
m_Geometry.m_Color.r = 255;
m_Geometry.m_Color.g = 255;
m_Geometry.m_Color.b = 255;
m_Geometry.m_Color.a = 255;
m_Geometry.m_TopColor.r = 255;
m_Geometry.m_TopColor.g = 255;
m_Geometry.m_TopColor.b = 255;
m_Geometry.m_TopColor.a = 255;
m_Geometry.m_BottomColor.r = 255;
m_Geometry.m_BottomColor.g = 255;
m_Geometry.m_BottomColor.b = 255;
m_Geometry.m_BottomColor.a = 255;
m_Geometry.m_bHorizontalGradient = false;
SetText( m_CharText );
SetFont( m_FontName );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGameText::~CGameText()
{
if ( m_UnicodeText )
{
delete[] m_UnicodeText;
m_UnicodeText = NULL;
}
};
//-----------------------------------------------------------------------------
// Create game text using dme elements
//-----------------------------------------------------------------------------
bool CGameText::Unserialize( CDmxElement *pGraphic )
{
pGraphic->UnpackIntoStructure( this, s_GameTextUnpack );
// GEOMETRY
// Geometry for text is generated. This is because you don't know it until you know the localized text.
// ANIMSTATES
CDmxAttribute *pImageAnims = pGraphic->GetAttribute( "imageanims" );
if ( !pImageAnims || pImageAnims->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &imageanims = pImageAnims->GetArray< CDmxElement * >( );
int nCount = imageanims.Count();
for ( int i = 0; i < nCount; ++i )
{
CAnimData *pAnimData = new CAnimData;
if ( !pAnimData->Unserialize( imageanims[i] ) )
{
delete pAnimData;
return false;
}
m_Anims.AddToTail( pAnimData );
}
SetText( m_CharText );
SetFont( m_FontName );
SetState( "default" );
return true;
}
//-----------------------------------------------------------------------------
// The attributes that can be modified by scripting are a subset of the DME ones.
//-----------------------------------------------------------------------------
KeyValues *CGameText::HandleScriptCommand( KeyValues *args )
{
char const *szCommand = args->GetName();
if ( !Q_stricmp( "SetText", szCommand ) )
{
const char *text = args->GetString( "text" );
SetText( text );
return NULL;
}
else if ( !Q_stricmp( "SetAllCaps", szCommand ) )
{
m_bAllCaps = args->GetBool( "allcaps", false );
return NULL;
}
else if ( !Q_stricmp( "SetFont", szCommand ) )
{
SetFont( args->GetString( "fontname" ) );
return NULL;
}
else if ( !Q_stricmp( "SetJustification", szCommand ) )
{
// FIXME
m_Justification = args->GetInt( "justfication", 0 );
return NULL;
}
else if ( !Q_stricmp( "SetTopColor", szCommand ) )
{
Color c = args->GetColor( "color", Color( 255, 255, 255, 255 ) );
m_Geometry.m_TopColor.r = c[0];
m_Geometry.m_TopColor.g = c[1];
m_Geometry.m_TopColor.b = c[2];
m_Geometry.m_TopColor.a = c[3];
return NULL;
}
else if ( !Q_stricmp( "SetBottomColor", szCommand ) )
{
Color c = args->GetColor( "color", Color( 255, 255, 255, 255 ) );
m_Geometry.m_BottomColor.r = c[0];
m_Geometry.m_BottomColor.g = c[1];
m_Geometry.m_BottomColor.b = c[2];
m_Geometry.m_BottomColor.a = c[3];
return NULL;
}
else if ( !Q_stricmp( "GetFont", szCommand ) )
{
return new KeyValues( "", "font", m_FontName.Get() );
}
return CGameGraphic::HandleScriptCommand( args );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::SetFont( const char *pFontName )
{
m_FontName = pFontName;
if ( m_FontName.Length() )
{
m_Font = g_pGameUISystemMgrImpl->GetCurrentScheme()->GetFont( m_FontName, true );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::SetFont( FontHandle_t font )
{
m_Font = font;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
FontHandle_t CGameText::GetFont()
{
return m_Font;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::SetJustification( Justification_e justify )
{
m_Justification = justify;
}
//-----------------------------------------------------------------------------
// Purpose: takes the string and looks it up in the localization file to convert it to unicode
//-----------------------------------------------------------------------------
void CGameText::SetText( const char *text )
{
if ( !text )
{
text = "";
}
// check for localization
if ( *text == '#' )
{
// try lookup in localization tables
m_UnlocalizedTextSymbol = g_pVGuiLocalize->FindIndex( text + 1 );
if ( m_UnlocalizedTextSymbol != vgui::INVALID_STRING_INDEX )
{
wchar_t *unicode = g_pVGuiLocalize->GetValueByIndex( m_UnlocalizedTextSymbol );
SetText(unicode);
return;
}
}
// convert the ansi string to unicode and use that
wchar_t unicode[1024];
g_pVGuiLocalize->ConvertANSIToUnicode( text, unicode, sizeof(unicode) );
SetText( unicode );
}
//-----------------------------------------------------------------------------
// Purpose: sets unicode text directly
//-----------------------------------------------------------------------------
void CGameText::SetText( const wchar_t *unicode, bool bClearUnlocalizedSymbol )
{
if ( bClearUnlocalizedSymbol )
{
// Clear out unlocalized text symbol so that changing dialog variables
// doesn't stomp over the custom unicode string we're being set to.
m_UnlocalizedTextSymbol = vgui::INVALID_STRING_INDEX;
}
if (!unicode)
{
unicode = L"";
}
// reallocate the buffer if necessary
short textLen = (short)wcslen( unicode );
if ( textLen >= m_TextBufferLen )
{
if ( m_UnicodeText )
{
delete [] m_UnicodeText;
m_UnicodeText = NULL;
}
m_TextBufferLen = (short)( textLen + 1 );
m_UnicodeText = new wchar_t[ m_TextBufferLen ];
}
// store the text as unicode
wcscpy( m_UnicodeText, unicode );
SetupVertexColors();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::UpdateGeometry()
{
if ( m_CurrentState == -1 )
return;
Assert( m_CurrentState < m_Anims.Count() );
DmeTime_t flAnimTime = GetAnimationTimePassed();
// Update color
m_Anims[ m_CurrentState ]->m_ColorAnim.GetValue( flAnimTime, &m_Geometry.m_Color );
// Update center location
m_Anims[ m_CurrentState ]->m_CenterPosAnim.GetValue( flAnimTime, &m_Geometry.m_Center );
// Update scale
m_Anims[ m_CurrentState ]->m_ScaleAnim.GetValue( flAnimTime, &m_Geometry.m_Scale );
// Update rotation
m_Anims[ m_CurrentState ]->m_RotationAnim.GetValue( flAnimTime, &m_Geometry.m_Rotation );
// Update rotation
m_Anims[ m_CurrentState ]->m_FontAnim.GetValue( flAnimTime, &m_FontName );
SetFont( m_FontName );
}
//-----------------------------------------------------------------------------
// Rendering helper
// For text rendering the starting position is top left
// Center text according to justification.
//-----------------------------------------------------------------------------
void CGameText::GetStartingTextPosition( int &x, int &y )
{
x = 0;
y = -GetTextRenderHeight()/2;
switch ( m_Justification )
{
case JUSTIFICATION_LEFT:
break;
case JUSTIFICATION_CENTER:
x = -GetTextRenderWidth()/2;
break;
case JUSTIFICATION_RIGHT:
x = -GetTextRenderWidth();
break;
default:
Assert(0);
break;
}
}
//-----------------------------------------------------------------------------
// Rendering helper
// Determine what list to put this quad into, and make an entry slot for it.
//-----------------------------------------------------------------------------
CRenderGeometry *CGameText::GetGeometryEntry( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex, int fontTextureID )
{
CRenderGeometry *pRenderGeometry = NULL;
if ( renderGeometryLists[firstListIndex].Count() != 0 )
{
for ( int j = firstListIndex; j < renderGeometryLists.Count(); ++j )
{
if ( fontTextureID == renderGeometryLists[j][0].m_FontTextureID )
{
int index = renderGeometryLists[j].AddToTail();
pRenderGeometry = &renderGeometryLists[j][index];
break;
}
}
}
// Didn't find a match for this textureID, time to make a new list of quads for this texture.
if ( pRenderGeometry == NULL )
{
int newListIndex;
if ( renderGeometryLists[firstListIndex].Count() == 0 ) // This is the first quad we are adding to this font layer.
{
newListIndex = firstListIndex;
}
else
{
newListIndex = renderGeometryLists.AddToTail();
}
int index = renderGeometryLists[newListIndex].AddToTail();
pRenderGeometry = &renderGeometryLists[newListIndex][index];
}
return pRenderGeometry;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::SetupVertexColors()
{
// There is no text to generate if these are not set.
if ( !m_UnicodeText )
return;
m_Geometry.m_VertexColors.RemoveAll();
color32 c;
c.r = 255;
c.g = 255;
c.b = 255;
c.a = 255;
for ( wchar_t *wsz = m_UnicodeText; *wsz != 0; wsz++ )
{
// Create 4 vertex colors per letter.
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
m_Geometry.m_VertexColors.AddToTail( c );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameText::UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
if ( !m_Geometry.m_bVisible )
return;
// There is no text to generate if these are not set.
if ( !m_UnicodeText )
return;
if ( m_Font == vgui::INVALID_FONT)
return;
m_Geometry.SetResultantColor( parentColor );
int x, y;
GetStartingTextPosition( x, y );
FontCharRenderInfo info;
info.currentFont = m_Font;
info.drawType = FONT_DRAW_DEFAULT;
int letterIndex = 0;
m_Geometry.m_RelativePositions.RemoveAll();
for ( wchar_t *wsz = m_UnicodeText; *wsz != 0; wsz++, letterIndex += 4 )
{
Assert( letterIndex < m_Geometry.m_VertexColors.Count() );
// Update FontCharRenderInfo
info.x = x;
info.y = y;
info.ch = wsz[0];
if ( m_bAllCaps )
{
info.ch = towupper( info.ch );
}
Vector2D relPositions[4];
g_pGameUISystemSurface->GetUnicodeCharRenderPositions( info, relPositions );
// get the character texture from the cache and the char's texture coords.
float *texCoords = NULL; // note this returns the static from the fonttexturecache... FIXME?
g_pGameUISystemSurface->GetTextureForChar( info, &texCoords );
x += g_pGameUISystemSurface->GetCharacterWidth( m_Font, info.ch );
// Get a geometry from the correct texture list.
CRenderGeometry *pRenderGeometry = GetGeometryEntry( renderGeometryLists, firstListIndex, info.textureId );
Assert( pRenderGeometry != NULL );
// Populate the new entry.
pRenderGeometry->m_FontTextureID = info.textureId;
Vector screenPosition;
Vector relativePosition;
// Top left
relativePosition.Init( relPositions[0].x, relPositions[0].y, 0 );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relPositions[0].x, relPositions[0].y ) );
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenPosition );
pRenderGeometry->m_Positions.AddToTail( Vector2D( floor( screenPosition.x ), floor( screenPosition.y ) ) );
pRenderGeometry->m_VertexColors.AddToTail( m_Geometry.m_VertexColors[letterIndex] );
pRenderGeometry->m_TextureCoords.AddToTail( Vector2D( texCoords[0], texCoords[1] ) );
// Top right
relativePosition.Init( relPositions[1].x, relPositions[1].y, 0 );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relPositions[1].x, relPositions[1].y ) );
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenPosition );
pRenderGeometry->m_Positions.AddToTail( Vector2D( floor( screenPosition.x ), floor( screenPosition.y ) ) );
pRenderGeometry->m_VertexColors.AddToTail( m_Geometry.m_VertexColors[letterIndex + 1] );
pRenderGeometry->m_TextureCoords.AddToTail( Vector2D( texCoords[2], texCoords[1] ) );
// Bottom right
relativePosition.Init( relPositions[2].x, relPositions[2].y, 0 );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relPositions[2].x, relPositions[2].y ) );
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenPosition );
pRenderGeometry->m_Positions.AddToTail( Vector2D( floor( screenPosition.x ), floor( screenPosition.y ) ) );
pRenderGeometry->m_VertexColors.AddToTail( m_Geometry.m_VertexColors[letterIndex + 2] );
pRenderGeometry->m_TextureCoords.AddToTail( Vector2D( texCoords[2], texCoords[3] ) );
// Bottom left
relativePosition.Init( relPositions[3].x, relPositions[3].y, 0 );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relPositions[3].x, relPositions[3].y ) );
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenPosition );
pRenderGeometry->m_Positions.AddToTail( Vector2D( floor( screenPosition.x ), floor( screenPosition.y ) ) );
pRenderGeometry->m_VertexColors.AddToTail( m_Geometry.m_VertexColors[letterIndex + 3] );
pRenderGeometry->m_TextureCoords.AddToTail( Vector2D( texCoords[0], texCoords[3] ) );
pRenderGeometry->m_AnimationRate = m_Geometry.m_AnimationRate;
pRenderGeometry->m_AnimStartTime = m_Geometry.m_AnimStartTime;
pRenderGeometry->m_bAnimate = m_Geometry.m_bAnimate;
pRenderGeometry->m_pImageAlias = NULL;
}
m_Geometry.CalculateExtents();
}
//-----------------------------------------------------------------------------
// Have to do this separately because extents are drawn as rects.
//-----------------------------------------------------------------------------
void CGameText::DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
color32 extentLineColor = { 0, 25, 255, 255 };
m_Geometry.DrawExtents( renderGeometryLists, firstListIndex, extentLineColor );
}
//-----------------------------------------------------------------------------
// Purpose: Get the size of a text string in pixels
//-----------------------------------------------------------------------------
void CGameText::GetTextSize( int &wide, int &tall )
{
wide = 0;
tall = 0;
if ( m_Font == vgui::INVALID_FONT )
return;
// For height, use the remapped font
tall = GetTextRenderHeight();
wide = GetTextRenderWidth();
}
//-----------------------------------------------------------------------------
// Return height of text in pixels
//-----------------------------------------------------------------------------
int CGameText::GetTextRenderWidth()
{
int wordWidth = 0;
int textLen = wcslen( m_UnicodeText );
for ( int i = 0; i < textLen; i++ )
{
wchar_t ch = m_UnicodeText[ i ];
if ( m_bAllCaps )
{
ch = towupper( ch );
}
// handle stupid special characters, these should be removed
if ( ch == '&' && m_UnicodeText[ i + 1 ] != 0 )
{
continue;
}
wordWidth += g_pGameUISystemSurface->GetCharacterWidth( m_Font, ch );
}
return wordWidth;
}
//-----------------------------------------------------------------------------
// Return width of text in pixels
//-----------------------------------------------------------------------------
int CGameText::GetTextRenderHeight()
{
return g_pGameUISystemSurface->GetFontTall( m_Font );
}
//-----------------------------------------------------------------------------
// Note corner colors will be stomped if the base graphic's color changes.
//-----------------------------------------------------------------------------
void CGameText::SetColor( color32 c )
{
m_Geometry.m_TopColor = c;
m_Geometry.m_BottomColor = c;
// Remove first to force the new colors in.
m_Geometry.m_VertexColors.RemoveAll();
SetupVertexColors();
}
//-----------------------------------------------------------------------------
// Determine if x,y is inside the graphic.
//-----------------------------------------------------------------------------
bool CGameText::HitTest( int x, int y )
{
if ( !m_Geometry.m_bVisible )
return false;
// Just using extents for now, note extents don't take into account rotation.
Vector2D point0( m_Geometry.m_Extents.m_TopLeft.x, m_Geometry.m_Extents.m_TopLeft.y );
Vector2D point1( m_Geometry.m_Extents.m_BottomRight.x, m_Geometry.m_Extents.m_TopLeft.y );
Vector2D point2( m_Geometry.m_Extents.m_BottomRight.x, m_Geometry.m_Extents.m_BottomRight.y );
Vector2D point3( m_Geometry.m_Extents.m_TopLeft.x, m_Geometry.m_Extents.m_BottomRight.y );
if ( PointTriangleHitTest( point0, point1, point2, Vector2D( x, y ) ) )
{
//Msg( "%d, %d hit\n", x, y );
return true;
}
if ( PointTriangleHitTest( point0, point2, point3, Vector2D( x, y ) ) )
{
//Msg( "%d, %d hit\n", x, y );
return true;
}
return false;
}

View File

@@ -0,0 +1,95 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMETEXT_H
#define GAMETEXT_H
#ifdef _WIN32
#pragma once
#endif
#include "vgui_surfacelib/ifontsurface.h"
#include "vgui/ilocalize.h"
#include "gamegraphic.h"
#include "dmxloader/dmxelement.h"
#include "animdata.h"
#include "gameuisystemmgr.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CGameText : public CGameGraphic
{
DECLARE_DMXELEMENT_UNPACK()
public:
CGameText( const char *pName );
virtual ~CGameText();
bool Unserialize( CDmxElement *pGraphic );
virtual KeyValues * HandleScriptCommand( KeyValues *args );
void SetFont( const char *pFontName );
void SetText( const char *text );
// where text should go relative to center position.
enum Justification_e
{
JUSTIFICATION_LEFT,
JUSTIFICATION_CENTER,
JUSTIFICATION_RIGHT,
};
void SetJustification( Justification_e justify );
void GetTextSize( int &wide, int &tall );
// from CGameGraphic
virtual void UpdateGeometry();
virtual void UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual void DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual void SetColor( color32 c );
virtual bool HitTest( int x, int y );
private:
CGameText();
void SetText( const wchar_t *unicode, bool bClearUnlocalizedSymbol = false );
void GetStartingTextPosition( int &x, int &y );
CRenderGeometry *GetGeometryEntry( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex, int fontTextureID );
void SetupVertexColors();
int GetTextRenderWidth();
int GetTextRenderHeight();
void SetFont( FontHandle_t font );
FontHandle_t GetFont();
void GetRenderInfo( CUtlVector< FontCharRenderInfo > &renderInfoList );
wchar_t *m_UnicodeText; // unicode version of the text
short m_TextBufferLen; // size of the text buffer
CUtlString m_CharText; // unlocalized version of the text
vgui::StringIndex_t m_UnlocalizedTextSymbol;
CUtlString m_FontName;
FontHandle_t m_Font;
bool m_bAllCaps;
int m_Justification;
};
#endif // GAMETEXT_H

View File

@@ -0,0 +1,891 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "gameuidefinition.h"
#include "gamelayer.h"
#include "gamerect.h"
#include "gametext.h"
#include "hitarea.h"
#include "graphicgroup.h"
#include "tier1/utlstringmap.h"
#include "tier1/utlbuffer.h"
#include "gameuisystem.h"
#include "gameuiscript.h"
#include "gameuisystemmgr.h"
#include "tier1/fmtstr.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "rendersystem/irenderdevice.h"
#include "rendersystem/irendercontext.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
static unsigned int s_nBaseTextureVarCache = 0;
BEGIN_DMXELEMENT_UNPACK ( CGameUIDefinition )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
END_DMXELEMENT_UNPACK( CGameUIDefinition, s_GameUIDefinitionUnpack )
//-----------------------------------------------------------------------------
// Constructor / Destructor.
//-----------------------------------------------------------------------------
CGameUIDefinition::CGameUIDefinition( IGameUISystem *pGameUISystem /* = NULL */ ) :
m_pGameUISystem( pGameUISystem )
{
m_pName = "";
m_bVisible = true;
m_bCanAcceptInput = false;
m_hScheme = 0;
m_pGameStage = NULL;
// All menus currently default so that
// if mouse focus changes then keyboard focus will match it.
// When keyboard focus changes in response to mouse focus we do not play any anims or send any
// script commands.
// This makes it so one hitarea in the menu has input focus at a time.
// If a menu needs them to be separate we can add a script command to turn this off.
bMouseFocusEqualsKeyboardFocus = true;
}
CGameUIDefinition::~CGameUIDefinition()
{
Shutdown();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDefinition::Shutdown()
{
int nGroups = m_Groups.Count();
for ( int i = 0; i < nGroups; ++i )
{
if ( m_Groups[i] )
{
delete m_Groups[i];
m_Groups[i] = NULL;
}
}
m_Groups.RemoveAll();
int nLayers = m_Layers.Count();
for ( int i = 0; i < nLayers; ++i )
{
m_Layers[i]->Shutdown();
delete m_Layers[i];
m_Layers[i] = NULL;
}
m_Layers.RemoveAll();
int nScripts = m_Scripts.Count();
for ( int i = 0; i < nScripts; ++i )
{
m_Scripts[i]->Shutdown();
delete m_Scripts[i];
m_Scripts[i] = NULL;
}
m_Scripts.RemoveAll();
}
//-----------------------------------------------------------------------------
// Creates an empty GameUI, just has one layer in it. No graphics.
//-----------------------------------------------------------------------------
bool CGameUIDefinition::CreateDefault( const char *pName )
{
m_pName = pName;
const char *pSchemeName = "resource\\ClientScheme.res";
m_hScheme = g_pGameUISchemeManager->LoadSchemeFromFile( pSchemeName, "nouiloadedscheme" );
// Static graphics
CGameLayer *pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_STATIC );
m_Layers.AddToTail( pGameLayer );
// Dynamic graphics.
pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_DYNAMIC );
m_Layers.AddToTail( pGameLayer );
// Font graphics
pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_FONT);
m_Layers.AddToTail( pGameLayer );
// Create a default stage
m_pGameStage = new CGameStage;
m_Groups.InsertBefore( 0, m_pGameStage );
m_bCanAcceptInput = false;
return true;
}
//-----------------------------------------------------------------------------
// Load in data from file
//-----------------------------------------------------------------------------
bool CGameUIDefinition::Unserialize( CDmxElement *pElement )
{
if ( Q_stricmp( pElement->GetTypeString(), "VguiCompiledDoc" ) )
{
return false;
}
pElement->UnpackIntoStructure( this, s_GameUIDefinitionUnpack );
const char *pSchemeName = pElement->GetValueString( "scheme" );
IGameUIScheme *pDefaultScheme = g_pGameUISchemeManager->GetDefaultScheme();
m_hScheme = g_pGameUISchemeManager->GetScheme( pSchemeName );
if ( m_hScheme == pDefaultScheme )
{
// It fell back to the default so didn't find it.
m_hScheme = g_pGameUISchemeManager->LoadSchemeFromFile( pSchemeName, pSchemeName );
Assert( m_hScheme );
}
g_pGameUISystemMgrImpl->SetScheme( m_hScheme );
CDmxAttribute *pLayers = pElement->GetAttribute( "layers" );
if ( !pLayers || pLayers->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
// Create dynamic image mapping.
CDmxAttribute *pImageListAttr = pElement->GetAttribute( "dynamicimagelist" );
if ( pImageListAttr )
{
const CUtlVector< CUtlString > &imageList = pImageListAttr->GetArray< CUtlString >( );
for ( int i = 0; i < imageList.Count(); ++i )
{
const char *pAlias = imageList[i].Get();
g_pGameUISystemMgrImpl->LoadImageAliasTexture( pAlias, "" );
}
}
// Map graphics to their DMX Element.
CUtlDict< CGameGraphic *, int > unserializedGraphicMapping;
const CUtlVector< CDmxElement * > &layers = pLayers->GetArray< CDmxElement * >( );
int nCount = layers.Count();
for ( int i = 0; i < nCount; ++i )
{
if ( !Q_stricmp( layers[i]->GetTypeString(), "DmeCompiledSubLayer" ) )
{
if ( !UnserializeLayer( layers[i], unserializedGraphicMapping ) )
{
return false;
}
}
}
// Add default layers, these layer will contain anything created from scripting.
// Static graphics
CGameLayer *pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_STATIC );
m_Layers.AddToTail( pGameLayer );
// Dynamic graphics.
pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_DYNAMIC );
m_Layers.AddToTail( pGameLayer );
// Font graphics
pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_FONT);
m_Layers.AddToTail( pGameLayer );
// Groups
CDmxAttribute *pGroups = pElement->GetAttribute( "groups" );
if ( !pGroups )
{
return true;
}
if ( pGroups->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &groups = pGroups->GetArray< CDmxElement * >( );
nCount = groups.Count();
if ( nCount == 0 )
{
Msg( "Error: No stage found" );
return false; // no stage would be fail.
}
bool bStageFound = false;
for ( int i = nCount-1; i >= 0; --i )
{
if ( !Q_stricmp( groups[i]->GetTypeString(), "DmeCompiledStage" ) )
{
bStageFound = true;
break;
}
}
if ( !bStageFound )
{
return false; // no stage would be fail.
}
// Add groups to the graphic mapping so groups can contain other groups.
// This means the groups get created and put in the list before they get unserialized.
// Groups should always be in order parents before children.
// This makes sure parents update before children in update loops
for ( int i = 0; i < nCount; ++i )
{
if ( !Q_stricmp( groups[i]->GetTypeString(), "DmeCompiledGroup" ) )
{
CGraphicGroup *pGraphicGroup = new CGraphicGroup;
char pBuf[255];
UniqueIdToString( groups[i]->GetId(), pBuf, 255 );
unserializedGraphicMapping.Insert( pBuf, pGraphicGroup );
m_Groups.AddToTail( pGraphicGroup );
}
else if ( !Q_stricmp( groups[i]->GetTypeString(), "DmeCompiledStage" ) )
{
Assert( i == 0 );
CGameStage *pGraphicGroup = new CGameStage;
m_Groups.InsertBefore( 0, pGraphicGroup );
m_pGameStage = pGraphicGroup;
}
}
// Now unserialize the groups
for ( int i = 0; i < nCount; ++i )
{
if ( !Q_stricmp( groups[i]->GetTypeString(), "DmeCompiledGroup" ) )
{
if ( !m_Groups[i]->Unserialize( groups[i], unserializedGraphicMapping ) )
{
return false;
}
}
else if ( !Q_stricmp( groups[i]->GetTypeString(), "DmeCompiledStage" ) )
{
Assert( i == 0 );
CGameStage *pStage = (CGameStage *)m_Groups[i];
if ( !pStage->Unserialize( groups[i], unserializedGraphicMapping ) )
{
return false;
}
}
else
{
Assert(0); // something is in the group list that isn't a group!
}
}
return true;
}
//-----------------------------------------------------------------------------
// Load in data from file for a layer
//-----------------------------------------------------------------------------
bool CGameUIDefinition::UnserializeLayer( CDmxElement *pLayer,
CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping )
{
// Static graphics
CDmxAttribute *pGraphics = pLayer->GetAttribute( "staticGraphics" );
// The layer may have no static graphics ( it could be only fonts! )
if ( pGraphics && pGraphics->GetType() == AT_ELEMENT_ARRAY )
{
CDmxAttribute *pGraphics = pLayer->GetAttribute( "staticGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphics->GetArray< CDmxElement * >( );
if ( graphics.Count() != 0 )
{
CGameLayer *pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_STATIC );
pGameLayer->Unserialize( pLayer, unserializedGraphicMapping );
m_Layers.AddToTail( pGameLayer );
}
}
// repeat above for dynamic graphics.
// The layer may have no dynamic graphics
if ( pGraphics && pGraphics->GetType() == AT_ELEMENT_ARRAY )
{
CDmxAttribute *pGraphics = pLayer->GetAttribute( "dynamicGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphics->GetArray< CDmxElement * >( );
if ( graphics.Count() != 0 )
{
CGameLayer *pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_DYNAMIC );
pGameLayer->Unserialize( pLayer, unserializedGraphicMapping );
m_Layers.AddToTail( pGameLayer );
}
}
// Font graphics
pGraphics = pLayer->GetAttribute( "fontGraphics" );
// The layer may have no font graphics
if ( pGraphics && pGraphics->GetType() == AT_ELEMENT_ARRAY )
{
CDmxAttribute *pGraphics = pLayer->GetAttribute( "fontGraphics" );
const CUtlVector< CDmxElement * > &graphics = pGraphics->GetArray< CDmxElement * >( );
if ( graphics.Count() != 0 )
{
CGameLayer *pGameLayer = new CGameLayer;
pGameLayer->SetLayerType( SUBLAYER_FONT );
pGameLayer->Unserialize( pLayer, unserializedGraphicMapping );
m_Layers.AddToTail( pGameLayer );
}
}
return true;
}
//-----------------------------------------------------------------------------
// Path is always vguiedit\menuname.lua
//-----------------------------------------------------------------------------
void CGameUIDefinition::InitializeScripts()
{
// First time?
if ( m_Scripts.Count() == 0 )
{
CFmtStr path[2];
path[0].sprintf( "vguiedit\\%s.lua", m_pName.Get() );
path[1].sprintf( "vguiedit\\%s\\%s.lua", m_pName.Get(), m_pName.Get() );
for ( int k = 0; k < ARRAYSIZE( path ); ++ k )
{
CFmtStr scriptPath;
scriptPath.sprintf( "scripts\\%s", path[k].Access() );
// Does this menu have a script?
if ( g_pFullFileSystem->FileExists( scriptPath, "MOD" ) )
{
CGameUIScript *pScript = new CGameUIScript();
bool bResult = pScript->SetScript( path[k], this );
if ( bResult )
{
m_Scripts.AddToTail( pScript );
DevMsg( "Loaded script %s for %s\n", scriptPath.Access(), m_pName.Get() );
break; // break as soon as the first script is loaded successfully
}
else
{
Warning( "Invalid script %s for %s\n", scriptPath.Access(), m_pName.Get() );
delete pScript;
}
}
else
{
DevMsg( "No default script %s found for %s\n", scriptPath.Access(), m_pName.Get() );
}
}
}
SetAcceptInput( false );
}
//-----------------------------------------------------------------------------
// Execute a script function
// The function to call is denoted by executionType
//-----------------------------------------------------------------------------
bool CGameUIDefinition::ExecuteScript( KeyValues *args, KeyValues **ppResult )
{
Assert( !ppResult || !*ppResult ); // storing return value, might overwrite caller's keyvalues
//////////////////////////////////////////////////////////////////////////
// TEMP: special events for unit-tests state control
char const *szEvent = args->GetName();
if ( !Q_stricmp( "AdvanceState", szEvent ) )
{
AdvanceState();
return true;
}
if ( !Q_stricmp( "StartPlaying", szEvent ) )
{
StartPlaying();
return true;
}
if ( !Q_stricmp( "StopPlaying", szEvent ) )
{
StopPlaying();
return true;
}
if ( !Q_stricmp( "ShowCursorCoords", szEvent ) )
{
g_pGameUISystemMgrImpl->ShowCursorCoords();
return true;
}
if ( !Q_stricmp( "ShowGraphicName", szEvent ) )
{
g_pGameUISystemMgrImpl->ShowGraphicName();
return true;
}
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
// Graphic access
if ( !Q_stricmp( "FindGraphic", szEvent ) )
{
CGameGraphic *pGraphic = FindGraphicByName( args->GetString( "graphic" ) );
if ( pGraphic && ppResult )
{
*ppResult = new KeyValues( "" );
(*ppResult)->SetInt( "graphichandle", pGraphic->GetScriptHandle() );
}
return true;
}
if ( !Q_stricmp( "SetInput", szEvent ) )
{
SetAcceptInput( args->GetBool( "input", true ) );
return true;
}
if ( !Q_stricmp( "InitAnims", szEvent ) )
{
InitAnims();
return true;
}
if ( !Q_stricmp( "Sound", szEvent ) )
{
if ( args->GetBool( "play", true ) )
g_pGameUISystemMgrImpl->PlayMenuSound( args->GetString( "sound" ) );
else
g_pGameUISystemMgrImpl->StopMenuSound( args->GetString( "sound" ) );
}
//////////////////////////////////////////////////////////////////////////
if ( !Q_stricmp( "setdynamictexture", szEvent ) )
{
g_pGameUISystemMgrImpl->LoadImageAliasTexture( args->GetString( "aliasname", "" ), args->GetString( "texturename", "" ) );
}
bool bExecuted = false;
if ( m_Scripts.Count() != 0 && m_Scripts[ 0 ] )
{
m_Scripts[ 0 ]->SetActive( true );
bExecuted = m_Scripts[ 0 ]->Execute( args, ppResult );
m_Scripts[ 0 ]->SetActive( false );
}
if ( !bExecuted )
{
// If the menu doesn't handle its exit just hide it.
if ( !Q_stricmp( szEvent, "OnExit" ) )
{
SetVisible( false );
return true;
}
}
return bExecuted;
}
//-----------------------------------------------------------------------------
// Return the number of layers in this menu
//-----------------------------------------------------------------------------
int CGameUIDefinition::GetLayerCount()
{
return m_Layers.Count();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDefinition::InvalidateSheetSymbols()
{
int nCount = m_Layers.Count();
for ( int j = 0; j < nCount; ++j )
{
m_Layers[j]->InvalidateSheetSymbol();
}
}
//-----------------------------------------------------------------------------
// Update from front to back so input consequences go right in.
//-----------------------------------------------------------------------------
void CGameUIDefinition::UpdateGeometry()
{
m_pGameStage->UpdateGeometry();
}
//-----------------------------------------------------------------------------
// Update the render to screen matrices of all graphics
// Children use thier parent's viewport/matrix and build off that.
//-----------------------------------------------------------------------------
void CGameUIDefinition::UpdateRenderTransforms( const Rect_t &viewport )
{
m_pGameStage->UpdateRenderTransforms( viewport );
}
//-----------------------------------------------------------------------------
// Get lists of rendering data needed to draw the ui.
// Each layer has a different type, static, dynamic, and font
// a new render list is created whenever the layer type changes
// and when the texture needed to render changes.
// Layers live in sets of 3's, static, dynamic and font.
// This preserves render order from the editor.
//-----------------------------------------------------------------------------
void CGameUIDefinition::GetRenderData( CUtlVector< LayerRenderLists_t > &renderLists )
{
int nLayers = m_Layers.Count();
for ( int i = 0; i < nLayers; ++i )
{
color32 stageColor = m_pGameStage->GetStageColor();
m_Layers[i]->UpdateRenderData( *this, stageColor, renderLists );
}
}
//-----------------------------------------------------------------------------
// Given a position, return the front most graphic under it.
//-----------------------------------------------------------------------------
CGameGraphic *CGameUIDefinition::GetGraphic( int x, int y )
{
int nLayers = m_Layers.Count();
for ( int i = nLayers-1; i >= 0; --i )
{
CGameGraphic *pGraphic = ( CGameGraphic * )m_Layers[i]->GetGraphic( x, y );
if ( pGraphic )
{
return pGraphic;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Given a position, return the front most graphic that can take input under it.
//-----------------------------------------------------------------------------
CHitArea *CGameUIDefinition::GetMouseFocus( int x, int y )
{
if ( CanAcceptInput() )
{
int nLayers = m_Layers.Count();
for ( int i = nLayers-1; i >= 0; --i )
{
CHitArea *pGraphic = ( CHitArea * )m_Layers[i]->GetMouseFocus( x, y );
if ( pGraphic )
{
return pGraphic;
}
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Given a graphic, return the next graphic that can receive focus.
// Note the default focus order is just the render order.
//-----------------------------------------------------------------------------
CHitArea *CGameUIDefinition::GetNextFocus( CHitArea *pCurrentGraphic )
{
if ( !CanAcceptInput() )
return NULL;
bool bGetNext = false;
if ( pCurrentGraphic == NULL )
{
bGetNext = true;
}
int nLayers = m_Layers.Count();
for ( int i = 0; i < nLayers; ++i )
{
CHitArea *pGraphic = ( CHitArea * )m_Layers[i]->GetNextFocus( bGetNext, pCurrentGraphic );
if ( pGraphic )
{
return pGraphic;
}
}
// We found no next one, we must be at the end then, restart from the back.
bGetNext = true;
for ( int i = 0; i < nLayers; ++i )
{
CHitArea *pGraphic = ( CHitArea * )m_Layers[i]->GetNextFocus( bGetNext, pCurrentGraphic );
if ( pGraphic )
{
return pGraphic;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Start playing animations
//-----------------------------------------------------------------------------
void CGameUIDefinition::StartPlaying()
{
m_pGameStage->StartPlaying();
int nCount = m_Layers.Count();
for ( int j = 0; j < nCount; ++j )
{
m_Layers[j]->StartPlaying();
}
}
//-----------------------------------------------------------------------------
// Stop playing animations
//-----------------------------------------------------------------------------
void CGameUIDefinition::StopPlaying()
{
m_pGameStage->StopPlaying();
int nCount = m_Layers.Count();
for ( int j = 0; j < nCount; ++j )
{
m_Layers[j]->StopPlaying();
}
}
//-----------------------------------------------------------------------------
// Move to the next known animation state
//-----------------------------------------------------------------------------
void CGameUIDefinition::AdvanceState()
{
m_pGameStage->AdvanceState();
int nCount = m_Layers.Count();
for ( int j = 0; j < nCount; ++j )
{
m_Layers[j]->AdvanceState();
}
}
//-----------------------------------------------------------------------------
// Set all graphics to "default" state.
//-----------------------------------------------------------------------------
void CGameUIDefinition::InitAnims()
{
m_pGameStage->SetState( "default" );
int nCount = m_Layers.Count();
for ( int j = 0; j < nCount; ++j )
{
m_Layers[j]->InitAnims();
}
}
//-----------------------------------------------------------------------------
// Given a graphic, build its scoped name.
//-----------------------------------------------------------------------------
void CGameUIDefinition::BuildScopedGraphicName( CUtlString &name, CGameGraphic *pGraphic )
{
if ( !pGraphic->GetGroup()->IsStageGroup() )
{
BuildScopedGraphicName( name, pGraphic->GetGroup() );
}
name += pGraphic->GetName();
if ( pGraphic->IsGroup() )
{
name += ":";
}
}
//-----------------------------------------------------------------------------
// Given a scoped name of a graphic, return it if it exists in this menu
//-----------------------------------------------------------------------------
CGameGraphic *CGameUIDefinition::GraphicExists( const char *pName ) const
{
if ( m_pGameStage->IsGraphicNamed( pName ) )
return m_pGameStage;
CSplitString nameparts( pName, ":");
CGameGraphic *parent = m_pGameStage;
CGameGraphic *pGraphic = NULL;
for ( int i = 0; i < nameparts.Count(); ++i )
{
pGraphic = parent->FindGraphicByName( nameparts[i] );
if ( pGraphic )
{
parent = pGraphic;
}
else
{
return NULL; // couldn't find it.
}
}
return pGraphic;
}
//-----------------------------------------------------------------------------
// Given a scoped name of a graphic, find it in this menu.
// This function expects to find the graphic
//-----------------------------------------------------------------------------
CGameGraphic *CGameUIDefinition::FindGraphicByName( const char *pName ) const
{
CGameGraphic *pGraphic = GraphicExists( pName );
if ( pGraphic )
{
return pGraphic;
}
else
{
Warning( "FindGraphicByName: Unable to find graphic named %s\n", pName );
return NULL; // couldn't find it.
}
}
//-----------------------------------------------------------------------------
// Add a text graphic to the front most layer of a given type
//-----------------------------------------------------------------------------
bool CGameUIDefinition::AddGraphicToLayer( CGameGraphic *pGraphic, int nLayerType )
{
pGraphic->SetGroup( m_pGameStage );
m_pGameStage->AddToGroup( pGraphic );
// Find the frontmost player of this type.
int nFrontLayer = -1;
for ( int i = m_Layers.Count()-1; i >= 0; --i )
{
if ( m_Layers[i]->GetLayerType() == nLayerType )
{
nFrontLayer = i;
break;
}
}
if ( nFrontLayer != -1 )
{
AddGraphic( pGraphic, nFrontLayer );
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Add a graphic to the given layer
//-----------------------------------------------------------------------------
void CGameUIDefinition::AddGraphic( CGameGraphic *pGraphic, int layerIndex )
{
Assert( layerIndex >= 0 );
Assert (layerIndex < m_Layers.Count() );
m_Layers[layerIndex]->AddGraphic( pGraphic );
}
//-----------------------------------------------------------------------------
// Remove this graphic from the UI
//-----------------------------------------------------------------------------
bool CGameUIDefinition::RemoveGraphic( CGameGraphic *pGraphic )
{
for ( int i = 0; i < m_Layers.Count(); ++i )
{
if ( m_Layers[i]->RemoveGraphic( pGraphic ) )
{
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Return true if this graphic is in this menu
//-----------------------------------------------------------------------------
bool CGameUIDefinition::HasGraphic( CGameGraphic *pGraphic )
{
for ( int i = 0; i < m_Layers.Count(); ++i )
{
if ( m_Layers[i]->HasGraphic( pGraphic ) )
{
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Set visibility of the gameui.
//-----------------------------------------------------------------------------
void CGameUIDefinition::SetVisible( bool bVisible )
{
m_bVisible = bVisible;
// Visibility can cause a focus change to be needed!
g_pGameUISystemMgrImpl->ForceFocusUpdate();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDefinition::UpdateAspectRatio( const Rect_t &viewport )
{
m_pGameStage->UpdateAspectRatio( viewport );
}
//-----------------------------------------------------------------------------
// Change the size of the stage.
//-----------------------------------------------------------------------------
void CGameUIDefinition::SetStageSize( int nWide, int nTall )
{
m_pGameStage->SetStageSize( nWide, nTall );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDefinition::GetStageSize( Vector2D &stageSize )
{
m_pGameStage->GetStageSize( stageSize );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDefinition::GetMaintainAspectRatioStageSize( Vector2D &stageSize )
{
m_pGameStage->GetMaintainAspectRatioStageSize( stageSize );
}

View File

@@ -0,0 +1,126 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEUIDEFINITION_H
#define GAMEUIDEFINITION_H
#ifdef _WIN32
#pragma once
#endif
#include "dmxloader/dmxelement.h"
#include "gamegraphic.h"
#include "gameuischeme.h"
#include "tier1/utlobjectreference.h"
#include "tier1/utldict.h"
#include "gamestage.h"
#include "tier1/UtlStringMap.h"
class CGameLayer;
class CGameUIScript;
enum EScriptExecution;
struct GameUIEvent_t;
struct GameGraphicMap_t
{
DmObjectId_t m_Id;
CGameGraphic *pGraphic;
};
//-----------------------------------------------------------------------------
// A template describing how a gameUI will function
// It loads CVguiCompiledDoc
//-----------------------------------------------------------------------------
class CGameUIDefinition
{
DECLARE_DMXELEMENT_UNPACK();
DECLARE_REFERENCED_CLASS( CGameUIDefinition );
public:
explicit CGameUIDefinition( IGameUISystem *pGameUISystem = NULL );
~CGameUIDefinition();
bool CreateDefault( const char *pName );
void Shutdown();
// Serialization, unserialization
bool Unserialize( CDmxElement *pElement );
void InitializeScripts();
void CallInitFunction();
// Scripts associated with the menu all live in a folder by that name.
// The main script for a menu is the same name as the menu.
const char *GetName() const { return m_pName; }
int GetLayerCount();
void InvalidateSheetSymbols();
void UpdateGeometry();
void UpdateRenderTransforms( const Rect_t &viewport );
void GetRenderData( CUtlVector< LayerRenderLists_t > &renderLists );
bool ExecuteScript( KeyValues *kvEvent, KeyValues **ppResult );
void StartPlaying();
void StopPlaying();
void AdvanceState();
void InitAnims();
IGameUISystem * GetGameUISystem() { return m_pGameUISystem; }
IGameUIScheme * GetScheme() { return m_hScheme; }
CGameGraphic *GraphicExists( const char *pName ) const;
CGameGraphic *FindGraphicByName( const char *pName ) const;
bool AddGraphicToLayer( CGameGraphic *pGraphic, int nLayerType );
bool RemoveGraphic( CGameGraphic *pGraphic );
bool HasGraphic( CGameGraphic *pGraphic );
CGameGraphic *GetGraphic( int x, int y );
CHitArea *GetMouseFocus( int x, int y );
CHitArea *GetNextFocus( CHitArea *pCurrentGraphic );
virtual void SetVisible( bool bVisible );
virtual bool GetVisible(){ return m_bVisible; }
void UpdateAspectRatio( const Rect_t &viewport );
void SetStageSize( int nWide, int nTall );
void GetStageSize( Vector2D &stageSize );
void GetMaintainAspectRatioStageSize( Vector2D &stageSize );
bool CanAcceptInput() { return m_bVisible && m_bCanAcceptInput; }
void SetAcceptInput( bool bAcceptInput ) { m_bCanAcceptInput = bAcceptInput; }
bool IsMouseFocusEqualToKeyboardFocus(){ return bMouseFocusEqualsKeyboardFocus; }
void BuildScopedGraphicName( CUtlString &name, CGameGraphic *pGraphic );
CGameUIScript * GetScript() { return m_Scripts.Count() ? m_Scripts[0] : NULL; }
private:
bool UnserializeLayer( CDmxElement *pLayer, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping );
void AddGraphic( CGameGraphic *pGraphic, int layerIndex );
CUtlString m_pName;
bool m_bVisible;
bool m_bCanAcceptInput;
CUtlVector< CGraphicGroup *> m_Groups;
CUtlVector< CGameLayer *> m_Layers;
CUtlVector< CGameUIScript * > m_Scripts;
IGameUISystem *m_pGameUISystem;
IGameUIScheme *m_hScheme;
CGameStage *m_pGameStage;
bool bMouseFocusEqualsKeyboardFocus;
};
#endif // GAMEUIDEFINITION_H

View File

@@ -0,0 +1,633 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "gameuidynamictextures.h"
#include "gamelayer.h"
#include "gamerect.h"
#include "tier1/utlstring.h"
#include "tier1/utlstringmap.h"
#include "tier1/utlbuffer.h"
#include "gameuisystemmgr.h"
#include "tier1/fmtstr.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/imaterialsystem.h"
#include "materialsystem/imesh.h"
#include "rendersystem/irenderdevice.h"
#include "rendersystem/irendercontext.h"
#include "tier1/keyvalues.h"
#include "materialsystem/IMaterialProxy.h"
#include "materialsystem/imaterialproxyfactory.h"
#include "gameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define GAMEUI_DYNAMIC_TEXTURE_SHEET_WIDTH 2048
#define GAMEUI_DYNAMIC_TEXTURE_SHEET_HEIGHT 2048
//-----------------------------------------------------------------------------
// A material proxy that resets the base texture to use the dynamic texture
//-----------------------------------------------------------------------------
class CGameControlsProxy : public IMaterialProxy
{
public:
CGameControlsProxy();
virtual ~CGameControlsProxy(){};
virtual bool Init( IMaterial *pMaterial, KeyValues *pKeyValues );
virtual void OnBind( void *pProxyData );
virtual void Release( void )
{
delete this;
}
virtual IMaterial *GetMaterial();
private:
IMaterialVar* m_BaseTextureVar;
};
CGameControlsProxy::CGameControlsProxy(): m_BaseTextureVar( NULL )
{
}
bool CGameControlsProxy::Init( IMaterial *pMaterial, KeyValues *pKeyValues )
{
bool bFoundVar;
m_BaseTextureVar = pMaterial->FindVar( "$basetexture", &bFoundVar, false );
return bFoundVar;
}
void CGameControlsProxy::OnBind( void *pProxyData )
{
const char *pBaseTextureName = ( const char * )pProxyData;
ITexture *pTexture = g_pMaterialSystem->FindTexture( pBaseTextureName, TEXTURE_GROUP_OTHER, true );
m_BaseTextureVar->SetTextureValue( pTexture );
}
IMaterial *CGameControlsProxy::GetMaterial()
{
return m_BaseTextureVar->GetOwningMaterial();
}
//-----------------------------------------------------------------------------
// Factory to create dynamic material. ( Return in this case. )
//-----------------------------------------------------------------------------
class CMaterialProxyFactory : public IMaterialProxyFactory
{
public:
IMaterialProxy *CreateProxy( const char *proxyName );
void DeleteProxy( IMaterialProxy *pProxy );
CreateInterfaceFn GetFactory();
};
static CMaterialProxyFactory s_DynamicMaterialProxyFactory;
IMaterialProxy *CMaterialProxyFactory::CreateProxy( const char *proxyName )
{
if ( Q_strcmp( proxyName, "GameControlsProxy" ) == NULL )
{
return static_cast< IMaterialProxy * >( new CGameControlsProxy );
}
return NULL;
}
void CMaterialProxyFactory::DeleteProxy( IMaterialProxy *pProxy )
{
}
CreateInterfaceFn CMaterialProxyFactory::GetFactory()
{
return Sys_GetFactoryThis();
}
//-----------------------------------------------------------------------------
// Constructor / Destructor.
//-----------------------------------------------------------------------------
CGameUIDynamicTextures::CGameUIDynamicTextures()
{
m_pDynamicTexturePacker = NULL;
m_RenderMaterial = NULL;
m_bRegenerate = false;
}
CGameUIDynamicTextures::~CGameUIDynamicTextures()
{
Shutdown();
}
//-----------------------------------------------------------------------------
// Init any render targets needed by the UI.
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::InitRenderTargets()
{
if ( !m_TexturePage.IsValid() )
{
m_TexturePage.InitRenderTarget( GAMEUI_DYNAMIC_TEXTURE_SHEET_WIDTH, GAMEUI_DYNAMIC_TEXTURE_SHEET_HEIGHT,
RT_SIZE_NO_CHANGE, IMAGE_FORMAT_ARGB8888,
MATERIAL_RT_DEPTH_NONE, false, "_rt_DynamicUI" );
}
if ( m_TexturePage.IsValid() )
{
int nSheetWidth = m_TexturePage->GetActualWidth();
int nSheetHeight = m_TexturePage->GetActualHeight();
m_pDynamicTexturePacker = new CTexturePacker( nSheetWidth, nSheetHeight, IsGameConsole() ? 0 : 1 );
KeyValues *pVMTKeyValues = new KeyValues( "GameControls" );
pVMTKeyValues->SetString( "$basetexture", "_rt_DynamicUI" );
CMaterialReference material;
// Material names must be different
CFmtStr materialName;
materialName.sprintf( "dynamictx_%s", "_rt_DynamicUI" );
material.Init( materialName, TEXTURE_GROUP_OTHER, pVMTKeyValues );
material->Refresh();
{
ImageAliasData_t imageData;
imageData.m_Width = nSheetWidth;
imageData.m_Height = nSheetHeight;
imageData.m_Material = material;
m_ImageAliasMap[ "_rt_DynamicUI" ] = imageData;
}
{
CTextureReference pErrorTexture;
pErrorTexture.Init( "error", TEXTURE_GROUP_OTHER, true );
ImageAliasData_t imageData;
imageData.m_Width = pErrorTexture->GetActualWidth();
imageData.m_Height = pErrorTexture->GetActualHeight();
imageData.m_szBaseTextureName = "error";
imageData.m_Material = NULL;
m_ImageAliasMap[ "errorImageAlias" ] = imageData;
}
pVMTKeyValues = new KeyValues( "GameControls" );
pVMTKeyValues->SetInt( "$ignorez", 1 );
KeyValues *pProxies = new KeyValues( "Proxies" );
pProxies->AddSubKey( new KeyValues( "GameControlsProxy" ) );
pVMTKeyValues->AddSubKey( pProxies );
m_RenderMaterial.Init( "dynamic_render_texture", TEXTURE_GROUP_OTHER, pVMTKeyValues );
m_RenderMaterial->Refresh();
g_pGameUISystemMgrImpl->InitImageAlias( "defaultImageAlias" );
g_pGameUISystemMgrImpl->LoadImageAliasTexture( "defaultImageAlias", "vguiedit/pixel" );
}
}
IMaterialProxy *CGameUIDynamicTextures::CreateProxy( const char *proxyName )
{
return s_DynamicMaterialProxyFactory.CreateProxy( proxyName );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::Shutdown()
{
m_RenderMaterial.Shutdown();
m_TexturePage.Shutdown();
if ( m_pDynamicTexturePacker )
{
delete m_pDynamicTexturePacker;
}
m_pDynamicTexturePacker = NULL;
m_RenderMaterial = NULL;
m_bRegenerate = false;
}
void CGameUIDynamicTextures::SetImageEntry( const char *pEntryName, ImageAliasData_t &imageData )
{
m_ImageAliasMap[ pEntryName ] = imageData;
}
//-----------------------------------------------------------------------------
// Associate this image alias name with a .vtf texture.
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::LoadImageAlias( const char *pAlias, const char *pBaseTextureName )
{
if ( !pAlias || !*pAlias )
return;
if ( !pBaseTextureName || !*pBaseTextureName )
return;
CFmtStr texturePath;
texturePath.sprintf( "materials\\%s.vtf", pBaseTextureName );
if ( !g_pFullFileSystem->FileExists( texturePath.Access(), IsGameConsole() ? "MOD" : "GAME" ) )
{
Warning( "Unable to find game ui dynamic texture \"%s\"\n", texturePath.Access() );
}
if ( Q_strcmp( pBaseTextureName, "" ) == 0 )
{
ImageAliasData_t *pImageData = GetImageAliasData( "errorImageAlias" );
ImageAliasData_t imageData;
imageData.Init();
imageData.m_XPos = pImageData->m_XPos;
imageData.m_YPos = pImageData->m_YPos;
imageData.m_Width = pImageData->m_Width;
imageData.m_Height = pImageData->m_Height;
imageData.m_szBaseTextureName = pImageData->m_szBaseTextureName;
imageData.m_Material = pImageData->m_Material;
imageData.m_bIsInSheet = pImageData->m_bIsInSheet;
imageData.m_nNodeIndex = pImageData->m_nNodeIndex;
SetImageEntry( pAlias, imageData );
return;
}
Msg( "Loading Alias %s Texture %s\n", pAlias, pBaseTextureName );
CTextureReference pTexture;
pTexture.Init( pBaseTextureName, TEXTURE_GROUP_OTHER, true );
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
int nodeIndex = -1;
if ( m_pDynamicTexturePacker )
{
if ( !IsErrorImageAliasData( pImageData ) )
{
if ( pImageData->m_nNodeIndex != -1 )
{
// We already had something packed in there for this alias.
// Remove the old alias texture
m_pDynamicTexturePacker->RemoveRect( pImageData->m_nNodeIndex );
}
// Set up new imagedata values
pImageData->m_Width = pTexture->GetActualWidth();
pImageData->m_Height = pTexture->GetActualHeight();
pImageData->m_szBaseTextureName = pBaseTextureName;
}
else
{
ImageAliasData_t imageData;
imageData.m_Width = pTexture->GetActualWidth();
imageData.m_Height = pTexture->GetActualHeight();
imageData.m_szBaseTextureName = pBaseTextureName;
imageData.m_nRefCount = pImageData->m_nRefCount;
SetImageEntry( pAlias, imageData );
pImageData = GetImageAliasData( pAlias );
Assert( !IsErrorImageAliasData( pImageData ) );
}
int nSheetWidth = 0;
int nSheetHeight = 0;
GetDynamicSheetSize( nSheetWidth, nSheetHeight );
Assert( nSheetWidth != 0 );
Assert( nSheetHeight != 0 );
// If our texture is huge in some way, don't bother putting it in the packed texture.
if ( ( pTexture->GetActualWidth() << 1 ) < nSheetWidth || ( pTexture->GetActualHeight() << 1 ) < nSheetHeight )
{
// Put this texture into the packed render target texture.
Rect_t texRect;
texRect.x = 0;
texRect.y = 0;
texRect.width = pTexture->GetActualWidth();
texRect.height = pTexture->GetActualHeight();
nodeIndex = m_pDynamicTexturePacker->InsertRect( texRect );
}
}
// For debugging this will make no packing happen. Each texture is one draw call
//nodeIndex = -1;
pImageData->m_nNodeIndex = nodeIndex;
LoadImageAliasTexture( pAlias, pBaseTextureName );
}
//-----------------------------------------------------------------------------
// Release the entry for this alias in the packer.
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::ReleaseImageAlias( const char *pAlias )
{
if ( Q_strcmp( pAlias, "_rt_DynamicUI" ) == 0 )
return;
if ( Q_strcmp( pAlias, "errorImageAlias" ) == 0 )
return;
if ( Q_strcmp( pAlias, "defaultImageAlias" ) == 0 )
return;
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
if ( pImageData )
{
Assert( pImageData->m_nRefCount > 0 );
pImageData->m_nRefCount--;
if ( pImageData->m_nRefCount == 0 )
{
if ( pImageData->m_bIsInSheet )
{
Msg( "Releasing Alias %s\n", pAlias );
m_pDynamicTexturePacker->RemoveRect( pImageData->m_nNodeIndex );
}
pImageData->Init();
}
}
}
//-----------------------------------------------------------------------------
// Associate this image alias name with a .vtf texture.
// This fxn loads the texture into the GameControls shader and makes a material
// for you
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::LoadImageAliasTexture( const char *pAlias, const char *pBaseTextureName )
{
if ( !pBaseTextureName || !*pBaseTextureName )
return;
CTextureReference pTexture;
pTexture.Init( pBaseTextureName, TEXTURE_GROUP_OTHER, true );
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
// Now set up the material for the new imagedata.
if ( pImageData->m_nNodeIndex == -1 )// it won't fit in the map, give it its own material, it is its own draw call.
{
// Material names must be different
CUtlVector<char *> words;
V_SplitString( pImageData->m_szBaseTextureName, "/", words );
CFmtStr materialName;
materialName.sprintf( "dynamictx_%s", words[words.Count()-1] );
KeyValues *pVMTKeyValues = new KeyValues( "GameControls" );
pVMTKeyValues->SetString( "$basetexture", pImageData->m_szBaseTextureName );
CMaterialReference material;
material.Init( materialName, TEXTURE_GROUP_OTHER, pVMTKeyValues );
material->Refresh();
pImageData->m_Material = material;
pImageData->m_bIsInSheet = false;
}
else // Do this if it fit in the packed texture.
{
if ( !m_RenderMaterial )
return;
pImageData->m_Material.Init( GetImageAliasMaterial( "_rt_DynamicUI" ) );
Assert( pImageData->m_Material );
pImageData->m_bIsInSheet = true;
const CTexturePacker::TreeEntry_t &newEntry = m_pDynamicTexturePacker->GetEntry( pImageData->m_nNodeIndex );
Assert( newEntry.rc.width == pImageData->m_Width );
Assert( newEntry.rc.height == pImageData->m_Height );
pImageData->m_XPos = newEntry.rc.x;
pImageData->m_YPos = newEntry.rc.y;
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
pRenderContext->PushRenderTargetAndViewport( m_TexturePage, NULL, pImageData->m_XPos, pImageData->m_YPos, pImageData->m_Width, pImageData->m_Height );
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Scale( 1, -1, 1 );
float flPixelOffsetX = 0.5f;
float flPixelOffsetY = 0.5f;
pRenderContext->Ortho( flPixelOffsetX, flPixelOffsetY, pImageData->m_Width + flPixelOffsetX, pImageData->m_Height + flPixelOffsetY, -1.0f, 1.0f );
//pRenderContext->Ortho( 0, 0, pImageData->m_Width, pImageData->m_Height, -1.0f, 1.0f );
// Clear to random color. Useful for testing.
//pRenderContext->ClearColor3ub( rand()%256, rand()%256, rand()%256 );
pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
pRenderContext->ClearBuffers( true, false );
// make sure there is no translation and rotation laying around
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PushMatrix();
pRenderContext->LoadIdentity();
pRenderContext->Bind( m_RenderMaterial, (void *)pImageData->m_szBaseTextureName.Get() );
int x = 0;
int y = 0;
int wide = pImageData->m_Width;
int tall = pImageData->m_Height;
unsigned char drawcolor[4];
drawcolor[0] = 255;
drawcolor[1] = 255;
drawcolor[2] = 255;
drawcolor[3] = 255;
IMesh *pMesh = pRenderContext->GetDynamicMesh( true );
if ( pMesh )
{
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Position3f( x, y, 0 );
meshBuilder.Color4ubv( drawcolor );
meshBuilder.TexCoord2f( 0, 0, 0 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( wide, y, 0 );
meshBuilder.Color4ubv( drawcolor );
meshBuilder.TexCoord2f( 0, 1, 0 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( wide, tall, 0 );
meshBuilder.Color4ubv( drawcolor );
meshBuilder.TexCoord2f( 0, 1, 1 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( x, tall, 0 );
meshBuilder.Color4ubv( drawcolor );
meshBuilder.TexCoord2f( 0, 0, 1 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.End();
pMesh->Draw();
}
// Restore the matrices
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_MODEL );
pRenderContext->PopMatrix();
pRenderContext->MatrixMode( MATERIAL_VIEW );
pRenderContext->PopMatrix();
pRenderContext->PopRenderTargetAndViewport();
}
}
//-----------------------------------------------------------------------------
// Return the material bound to this image alias.
// If the texture was not found you will see the purple and black checkerboard
// error texture.
//-----------------------------------------------------------------------------
IMaterial *CGameUIDynamicTextures::GetImageAliasMaterial( const char *pAlias )
{
if ( m_ImageAliasMap.Defined( pAlias ) )
{
return m_ImageAliasMap[pAlias].m_Material;
}
return m_ImageAliasMap[ "errorImageAlias" ].m_Material;
}
//-----------------------------------------------------------------------------
// Return the data bound to this image alias.
// If the alias was not found you will see the purple and black checkerboard
// error texture.
//-----------------------------------------------------------------------------
ImageAliasData_t *CGameUIDynamicTextures::GetImageAliasData( const char *pAlias )
{
if ( m_ImageAliasMap.Defined( pAlias ) )
{
return &m_ImageAliasMap[pAlias];
}
return &m_ImageAliasMap[ "errorImageAlias" ];
}
//-----------------------------------------------------------------------------
// Return true if this data is the error alias
//-----------------------------------------------------------------------------
bool CGameUIDynamicTextures::IsErrorImageAliasData( ImageAliasData_t *pData )
{
return ( &m_ImageAliasMap[ "errorImageAlias" ] ) == pData;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::GetDynamicSheetSize( int &nWidth, int &nHeight )
{
nWidth = m_TexturePage->GetActualWidth();
nHeight = m_TexturePage->GetActualHeight();
}
//-----------------------------------------------------------------------------
// Draw the dynamic texture associated with this alias at x, y
// It is drawn full size. This fxn is modeled off of CGameUISystemSurface::DrawFontTexture()
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::DrawDynamicTexture( const char *pAlias, int x, int y )
{
if ( !pAlias || !*pAlias )
return;
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
int wide = 0;
int tall = 0;
if ( !pImageData->m_bIsInSheet )
{
wide = pImageData->m_Width;
tall = pImageData->m_Height;
}
else
{
GetDynamicSheetSize( wide, tall );
}
color32 drawcolor;
drawcolor.r = 255;
drawcolor.g = 255;
drawcolor.b = 255;
drawcolor.a = 255;
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pImageData->m_Material );
if ( !pMesh )
return;
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Position3f( x, y, 0 );
meshBuilder.Color4ub( drawcolor.r, drawcolor.g, drawcolor.b, drawcolor.a );
meshBuilder.TexCoord3f( 0, 0, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x + wide, y, 0 );
meshBuilder.Color4ub( drawcolor.r, drawcolor.g, drawcolor.b, drawcolor.a );
meshBuilder.TexCoord3f( 0, 1, 0, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x + wide, y + tall, 0 );
meshBuilder.Color4ub( drawcolor.r, drawcolor.g, drawcolor.b, drawcolor.a );
meshBuilder.TexCoord3f( 0, 1, 1, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.Position3f( x, y + tall, 0 );
meshBuilder.Color4ub( drawcolor.r, drawcolor.g, drawcolor.b, drawcolor.a );
meshBuilder.TexCoord3f( 0, 0, 1, 0 );
meshBuilder.AdvanceVertex();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Reload all textures into the rendertarget.
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::OnRestore( int nChangeFlags )
{
m_bRegenerate = true;
}
//-----------------------------------------------------------------------------
// Reload all textures into the rendertarget.
//-----------------------------------------------------------------------------
void CGameUIDynamicTextures::RegenerateTexture( int nChangeFlags )
{
if ( !m_bRegenerate )
return;
int numEntries = m_ImageAliasMap.GetNumStrings();
for ( int i = 0; i < numEntries; ++i )
{
const char *pAlias = m_ImageAliasMap.String( i );
ImageAliasData_t *pImageData = GetImageAliasData( pAlias );
if ( IsErrorImageAliasData( pImageData ) )
continue;
if ( Q_strcmp( pAlias, "_rt_DynamicUI") == 0 )
continue;
if ( !pImageData->m_szBaseTextureName || !*pImageData->m_szBaseTextureName )
continue;
ITexture *pTexture = g_pMaterialSystem->FindTexture( pImageData->m_szBaseTextureName.Get(), TEXTURE_GROUP_OTHER, true );
Assert( pTexture );
pTexture->Download();
LoadImageAliasTexture( pAlias, pImageData->m_szBaseTextureName );
}
}

View File

@@ -0,0 +1,108 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEUIDYNAMICTEXTURES_H
#define GAMEUIDYNAMICTEXTURES_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlobjectreference.h"
#include "tier1/utldict.h"
#include "tier1/utlstring.h"
#include "tier1/utlstringmap.h"
#include "materialsystem/materialsystemutil.h"
#include "materialsystem/imaterialproxy.h"
#include "bitmap/texturepacker.h"
//----------------------------------------------------------------------------
// Helper class for entries in the packer
//----------------------------------------------------------------------------
class ImageAliasData_t
{
public:
ImageAliasData_t()
{
Init();
}
void Init()
{
m_XPos = 0;
m_YPos = 0;
m_Width = 0;
m_Height = 0;
m_szBaseTextureName = "";
m_Material = NULL;
m_bIsInSheet = false;
m_nNodeIndex = -1;
m_nRefCount = 0;
}
int m_XPos;
int m_YPos;
int m_Width;
int m_Height;
CUtlString m_szBaseTextureName;
CMaterialReference m_Material;
bool m_bIsInSheet;
int m_nNodeIndex;
int m_nRefCount;
private:
ImageAliasData_t( ImageAliasData_t &ref ) { }
};
//-----------------------------------------------------------------------------
// A template describing how a gameUI will function
// It loads CVguiCompiledDoc
//-----------------------------------------------------------------------------
class CGameUIDynamicTextures
{
public:
CGameUIDynamicTextures();
~CGameUIDynamicTextures();
void InitRenderTargets();
IMaterialProxy *CreateProxy( const char *proxyName );
void Shutdown();
void SetImageEntry( const char *pEntryName, ImageAliasData_t &imageData );
void LoadImageAlias( const char *pAlias, const char *pBaseTextureName );
void ReleaseImageAlias( const char *pAlias );
IMaterial *GetImageAliasMaterial( const char *pAlias );
ImageAliasData_t *GetImageAliasData( const char *pAlias );
bool IsErrorImageAliasData( ImageAliasData_t *pData );
void GetDynamicSheetSize( int &nWidth, int &nHeight );
void DrawDynamicTexture( const char *pAlias, int x, int y );
void OnRestore( int nChangeFlags );
void RegenerateTexture( int nChangeFlags );
private:
void LoadImageAliasTexture( const char *pAlias, const char *pBaseTextureName );
// Stores the actual texture we're writing into
CTextureReference m_TexturePage;
CTexturePacker *m_pDynamicTexturePacker;
CUtlStringMap< ImageAliasData_t > m_ImageAliasMap;
CMaterialReference m_RenderMaterial; // used to render dynamic textures into the render target.
bool m_bRegenerate;
};
#endif // GAMEUIDYNAMICTEXTURES_H

View File

@@ -0,0 +1,885 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#define SUPPORT_CUSTOM_FONT_FORMAT
#ifdef SUPPORT_CUSTOM_FONT_FORMAT
#define _WIN32_WINNT 0x0500
#endif
#include "gameuischeme.h"
#include "gameuisystemsurface.h"
#include "vgui/ISystem.h"
#include "tier1/utlbuffer.h"
#include "gameuisystemmgr.h"
#include "tier1/KeyValues.h"
#include "vgui_surfacelib/fontmanager.h"
#include "vgui/isurface.h"
#include "vgui_controls/controls.h" // has system()
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#include "xbox/xboxstubs.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define FONT_ALIAS_NAME_LENGTH 64
CGameUISchemeManager g_GameUISchemeManager;
CGameUISchemeManager *g_pGameUISchemeManager = &g_GameUISchemeManager;
//-----------------------------------------------------------------------------
// Helper function for getting the language the game ui should use.
//-----------------------------------------------------------------------------
static void HelperGetLanguage( char *pLanguageBuf, int bufSize )
{
bool bValid = false;
if ( IsPC() )
{
bValid = vgui::system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", pLanguageBuf, bufSize - 1 );
}
else
{
Q_strncpy( pLanguageBuf, XBX_GetLanguageString(), bufSize );
bValid = true;
}
if ( !bValid )
{
Q_strncpy( pLanguageBuf, "english", bufSize );
}
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameUISchemeManager::CGameUISchemeManager()
{
// 0th element is null, since that would be an invalid handle
CGameUIScheme *nullScheme = new CGameUIScheme();
m_Schemes.AddToTail(nullScheme);
Assert( g_pGameUISystemSurface );
}
//-----------------------------------------------------------------------------
// Purpose: Destructor
//-----------------------------------------------------------------------------
CGameUISchemeManager::~CGameUISchemeManager()
{
int i;
for ( i = 0; i < m_Schemes.Count(); i++ )
{
delete m_Schemes[i];
m_Schemes[i] = NULL;
}
m_Schemes.RemoveAll();
Shutdown( false );
}
//-----------------------------------------------------------------------------
// Purpose: Reloads the schemes from the files
//-----------------------------------------------------------------------------
void CGameUISchemeManager::ReloadSchemes()
{
int count = m_Schemes.Count();
Shutdown( false );
// reload the scheme
for (int i = 1; i < count; i++)
{
LoadSchemeFromFile( m_Schemes[i]->GetFileName(), m_Schemes[i]->GetName() );
}
}
//-----------------------------------------------------------------------------
// Purpose: Reload the fonts in all schemes
//-----------------------------------------------------------------------------
void CGameUISchemeManager::ReloadFonts( int inScreenTall )
{
for (int i = 1; i < m_Schemes.Count(); i++)
{
m_Schemes[i]->ReloadFontGlyphs( inScreenTall );
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUISchemeManager::Shutdown( bool full )
{
// Full shutdown kills the null scheme
for( int i = full ? 0 : 1; i < m_Schemes.Count(); i++ )
{
m_Schemes[i]->Shutdown( full );
}
if ( full )
{
m_Schemes.RemoveAll();
}
}
//-----------------------------------------------------------------------------
// Purpose: Find an already loaded scheme
//-----------------------------------------------------------------------------
IGameUIScheme * CGameUISchemeManager::FindLoadedScheme( const char *pFilename )
{
// Find the scheme in the list of already loaded schemes
for ( int i = 1; i < m_Schemes.Count(); i++ )
{
char const *schemeFileName = m_Schemes[i]->GetFileName();
if ( !stricmp( schemeFileName, pFilename ) )
return m_Schemes[i];
}
return NULL;
}
//-----------------------------------------------------------------------------
// First scheme loaded becomes the default scheme,
// and all subsequent loaded scheme are derivatives of that
//-----------------------------------------------------------------------------
IGameUIScheme * CGameUISchemeManager::LoadSchemeFromFileEx( const char *pFilename, const char *tag )
{
// Look to see if we've already got this scheme...
CGameUIScheme * hScheme = ( CGameUIScheme * ) FindLoadedScheme( pFilename );
if ( hScheme )
{
if ( hScheme->IsActive() )
{
if ( IsPC() )
{
hScheme->ReloadFontGlyphs();
}
return hScheme;
}
}
else
{
hScheme = new CGameUIScheme();
m_Schemes.AddToTail( hScheme );
}
KeyValues *data;
data = new KeyValues("Scheme");
data->UsesEscapeSequences( true ); // VGUI uses this
// look first in skins directory
bool result = data->LoadFromFile( g_pFullFileSystem, pFilename, "SKIN" );
if (!result)
{
result = data->LoadFromFile( g_pFullFileSystem, pFilename, "GAME" );
if ( !result )
{
// look in any directory
result = data->LoadFromFile( g_pFullFileSystem, pFilename, NULL );
}
}
if (!result)
{
data->deleteThis();
return 0;
}
if ( IsPC() )
{
ConVarRef cl_hud_minmode( "cl_hud_minmode", true );
if ( cl_hud_minmode.IsValid() && cl_hud_minmode.GetBool() )
{
data->ProcessResolutionKeys( "_minmode" );
}
}
hScheme->SetActive( true );
hScheme->LoadFromFile( pFilename, tag, data );
return hScheme;
}
//-----------------------------------------------------------------------------
// Purpose: loads a scheme from disk
//-----------------------------------------------------------------------------
IGameUIScheme * CGameUISchemeManager::LoadSchemeFromFile( const char *fileName, const char *tag )
{
return LoadSchemeFromFileEx( fileName, tag );
}
//-----------------------------------------------------------------------------
// Purpose: returns a handle to the default (first loaded) scheme
//-----------------------------------------------------------------------------
IGameUIScheme * CGameUISchemeManager::GetDefaultScheme()
{
if ( m_Schemes.Count() >= 2 )
return m_Schemes[1];
else if ( m_Schemes.Count() > 0 )
return m_Schemes[0];
else
return NULL;
}
//-----------------------------------------------------------------------------
// Purpose: returns a handle to the scheme identified by "tag"
//-----------------------------------------------------------------------------
IGameUIScheme * CGameUISchemeManager::GetScheme( const char *tag )
{
for ( int i=1; i<m_Schemes.Count(); i++ )
{
if ( !stricmp( tag, m_Schemes[i]->GetName() ) )
{
return m_Schemes[i];
}
}
return GetDefaultScheme(); // default scheme
}
//-----------------------------------------------------------------------------
// gets the proportional coordinates for doing screen-size independant panel layouts
// use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
//-----------------------------------------------------------------------------
int CGameUISchemeManager::GetProportionalScaledValueEx( CGameUIScheme *pScheme, int normalizedValue, int screenTall )
{
return GetProportionalScaledValue( normalizedValue, screenTall );
}
//-----------------------------------------------------------------------------
// Purpose: converts a value into proportional mode
//-----------------------------------------------------------------------------
int CGameUISchemeManager::GetProportionalScaledValue( int normalizedValue, int screenTall )
{
int tall;
if ( screenTall == -1 )
{
g_pGameUISystemMgrImpl->GetScreenHeightForFontLoading( tall );
}
else
{
tall = screenTall;
}
return GetProportionalScaledValue_( tall, normalizedValue );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CGameUISchemeManager::GetProportionalScaledValue_( int screenTall, int normalizedValue )
{
int baseWide, baseTall;
g_pGameUISystemSurface->GetProportionalBase( baseWide, baseTall );
double scale = (double)screenTall / (double)baseTall;
return (int)( normalizedValue * scale );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUISchemeManager::SpewFonts( void )
{
for ( int i = 1; i < m_Schemes.Count(); i++ )
{
m_Schemes[i]->SpewFonts();
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUISchemeManager::SetLanguage( const char *pLanguage )
{
g_pGameUISystemSurface->SetLanguage( pLanguage );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CGameUISchemeManager::GetLanguage()
{
return g_pGameUISystemSurface->GetLanguage();
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameUIScheme::CGameUIScheme()
{
m_pFileName = "";
m_pTag = "";
m_pData = NULL;
SetActive( false );
}
CGameUIScheme::~CGameUIScheme()
{
}
//-----------------------------------------------------------------------------
// Purpose: loads a scheme from from disk into memory
//-----------------------------------------------------------------------------
void CGameUIScheme::LoadFromFile( const char *pFilename, const char *inTag, KeyValues *inKeys )
{
COM_TimestampedLog( "CScheme::LoadFromFile( %s )", pFilename );
m_pFileName = pFilename;
m_pData = inKeys;
// override the scheme name with the tag name
KeyValues *name = m_pData->FindKey( "Name", true );
name->SetString("Name", inTag);
if ( inTag )
{
m_pTag = inTag;
}
else
{
Error( "You need to name the scheme (%s)!", m_pFileName.Get() );
m_pTag = "default";
}
LoadFonts();
}
//-----------------------------------------------------------------------------
// Purpose: Set the range of character values this font can be used on
//-----------------------------------------------------------------------------
bool CGameUIScheme::GetFontRange( const char *fontname, int &nMin, int &nMax )
{
for ( int i = 0 ; i < m_FontRanges.Count() ; i++ )
{
if ( Q_stricmp( m_FontRanges[i]._fontName.String(), fontname ) == 0 )
{
nMin = m_FontRanges[i]._min;
nMax = m_FontRanges[i]._max;
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Purpose: Get the range of character values this font can be used on
//-----------------------------------------------------------------------------
void CGameUIScheme::SetFontRange( const char *fontname, int nMin, int nMax )
{
for ( int i = 0 ; i < m_FontRanges.Count() ; i++ )
{
if ( Q_stricmp( m_FontRanges[i]._fontName.String(), fontname ) == 0 )
{
m_FontRanges[i]._min = nMin;
m_FontRanges[i]._max = nMax;
return;
}
}
// not already in our list
int iIndex = m_FontRanges.AddToTail();
m_FontRanges[iIndex]._fontName = fontname;
m_FontRanges[iIndex]._min = nMin;
m_FontRanges[iIndex]._max = nMax;
}
//-----------------------------------------------------------------------------
// Purpose: adds all the font specifications to the surface
//-----------------------------------------------------------------------------
void CGameUIScheme::LoadFonts()
{
// get our language
const char *pLanguage = g_GameUISchemeManager.GetLanguage();
// add our custom fonts
for ( KeyValues *kv = m_pData->FindKey("CustomFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey() )
{
const char *fontFile = kv->GetString();
if (fontFile && *fontFile)
{
g_pGameUISystemSurface->AddCustomFontFile( fontFile );
}
else
{
// we have a block to read
int nRangeMin = 0, nRangeMax = 0;
const char *pszName = NULL;
bool bUseRange = false;
for ( KeyValues *pData = kv->GetFirstSubKey(); pData != NULL; pData = pData->GetNextKey() )
{
const char *pszKey = pData->GetName();
if ( !Q_stricmp( pszKey, "font" ) )
{
fontFile = pData->GetString();
}
else if ( !Q_stricmp( pszKey, "name" ) )
{
pszName = pData->GetString();
}
else
{
// we must have a language
if ( Q_stricmp( pLanguage, pszKey ) == 0 ) // matches the language we're running?
{
// get the range
KeyValues *pRange = pData->FindKey( "range" );
if ( pRange )
{
bUseRange = true;
sscanf( pRange->GetString(), "%x %x", &nRangeMin, &nRangeMax );
if ( nRangeMin > nRangeMax )
{
int nTemp = nRangeMin;
nRangeMin = nRangeMax;
nRangeMax = nTemp;
}
}
}
}
}
if ( fontFile && *fontFile )
{
g_pGameUISystemSurface->AddCustomFontFile( fontFile );
if ( bUseRange )
{
SetFontRange( pszName, nRangeMin, nRangeMax );
}
}
}
}
// add bitmap fonts
for ( KeyValues *kv = m_pData->FindKey("BitmapFontFiles", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey() )
{
const char *fontFile = kv->GetString();
if (fontFile && *fontFile)
{
bool bSuccess = g_pGameUISystemSurface->AddBitmapFontFile( fontFile );
if ( bSuccess )
{
// refer to the font by a user specified symbol
g_pGameUISystemSurface->SetBitmapFontName( kv->GetName(), fontFile );
}
}
}
// create the fonts
for (KeyValues *kv = m_pData->FindKey("Fonts", true)->GetFirstSubKey(); kv != NULL; kv = kv->GetNextKey())
{
for ( int i = 0; i < 2; i++ )
{
// create the base font
bool proportionalFont = i ? true : false;
const char *fontName = GetMungedFontName( kv->GetName(), m_pTag.Get(), proportionalFont ); // first time it adds a normal font, and then a proportional one
FontHandle_t font = g_pGameUISystemSurface->CreateFont();
int j = m_FontAliases.AddToTail();
m_FontAliases[j]._fontName = fontName;
m_FontAliases[j]._trueFontName = kv->GetName();
m_FontAliases[j]._font = font;
m_FontAliases[j].m_bProportional = proportionalFont;
}
}
// load in the font glyphs
ReloadFontGlyphs();
}
//-----------------------------------------------------------------------------
// Purpose: Reloads all scheme fonts
// Supply a language if you don't want to use the one in the registry.
//-----------------------------------------------------------------------------
void CGameUIScheme::ReloadFontGlyphs( int inScreenTall )
{
int screenTall;
// get our current resolution
if ( inScreenTall == -1 )
{
//int screenWide;
g_pGameUISystemMgrImpl->GetScreenHeightForFontLoading( screenTall );
}
else // this will make fonts be the correct size in the editor, where the stage size is the screen size.
{
screenTall = inScreenTall;
}
// check our language; some have minimum sizes
int minimumFontHeight = GetMinimumFontHeightForCurrentLanguage( g_GameUISchemeManager.GetLanguage() );
// add the data to all the fonts
KeyValues *fonts = m_pData->FindKey( "Fonts", true );
for (int i = 0; i < m_FontAliases.Count(); i++)
{
KeyValues *kv = fonts->FindKey( m_FontAliases[i]._trueFontName.String(), true );
// walk through creating adding the first matching glyph set to the font
for ( KeyValues *fontdata = kv->GetFirstSubKey(); fontdata != NULL; fontdata = fontdata->GetNextKey() )
{
// skip over fonts not meant for this resolution
int fontYResMin = 0, fontYResMax = 0;
sscanf( fontdata->GetString( "yres", "" ), "%d %d", &fontYResMin, &fontYResMax );
if ( fontYResMin )
{
if ( !fontYResMax )
{
fontYResMax = fontYResMin;
}
// check the range
if ( screenTall < fontYResMin || screenTall > fontYResMax )
continue;
}
int flags = 0;
if (fontdata->GetInt( "italic" ))
{
flags |= FONTFLAG_ITALIC;
}
if (fontdata->GetInt( "underline" ))
{
flags |= FONTFLAG_UNDERLINE;
}
if (fontdata->GetInt( "strikeout" ))
{
flags |= FONTFLAG_STRIKEOUT;
}
if (fontdata->GetInt( "symbol" ))
{
flags |= FONTFLAG_SYMBOL;
}
if (fontdata->GetInt( "antialias" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_ANTIALIASED_FONTS ) )
{
flags |= FONTFLAG_ANTIALIAS;
}
if (fontdata->GetInt( "dropshadow" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_DROPSHADOW_FONTS ) )
{
flags |= FONTFLAG_DROPSHADOW;
}
if (fontdata->GetInt( "outline" ) && g_pGameUISystemSurface->SupportsFontFeature( FONT_FEATURE_OUTLINE_FONTS ) )
{
flags |= FONTFLAG_OUTLINE;
}
if (fontdata->GetInt( "custom" ))
{
flags |= FONTFLAG_CUSTOM;
}
if (fontdata->GetInt( "bitmap" ))
{
flags |= FONTFLAG_BITMAP;
}
if (fontdata->GetInt( "rotary" ))
{
flags |= FONTFLAG_ROTARY;
}
if (fontdata->GetInt( "additive" ))
{
flags |= FONTFLAG_ADDITIVE;
}
int fontTall = fontdata->GetInt( "tall" );
int blur = fontdata->GetInt( "blur" );
int scanlines = fontdata->GetInt( "scanlines" );
float scalex = fontdata->GetFloat( "scalex", 1.0f );
float scaley = fontdata->GetFloat( "scaley", 1.0f );
// only grow this font if it doesn't have a resolution filter specified
if ( ( !fontYResMin && !fontYResMax ) && m_FontAliases[i].m_bProportional )
{
fontTall = g_GameUISchemeManager.GetProportionalScaledValueEx( this, fontTall, screenTall );
blur = g_GameUISchemeManager.GetProportionalScaledValueEx( this, blur );
scanlines = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scanlines );
scalex = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scalex * 10000.0f ) * 0.0001f;
scaley = g_GameUISchemeManager.GetProportionalScaledValueEx( this, scaley * 10000.0f ) * 0.0001f;
}
// clip the font size so that fonts can't be too big
if ( fontTall > 127 )
{
fontTall = 127;
}
// check our minimum font height
if ( fontTall < minimumFontHeight )
{
fontTall = minimumFontHeight;
}
if ( flags & FONTFLAG_BITMAP )
{
// add the new set
g_pGameUISystemSurface->SetBitmapFontGlyphSet(
m_FontAliases[i]._font,
g_pGameUISystemSurface->GetBitmapFontName( fontdata->GetString( "name" ) ),
scalex,
scaley,
flags);
}
else
{
int nRangeMin, nRangeMax;
if ( GetFontRange( fontdata->GetString( "name" ), nRangeMin, nRangeMax ) )
{
// add the new set
g_pGameUISystemSurface->SetFontGlyphSet(
m_FontAliases[i]._font, fontdata->GetString( "name" ),
fontTall, fontdata->GetInt( "weight" ), blur, scanlines, flags, nRangeMin, nRangeMax);
}
else
{
// add the new set
g_pGameUISystemSurface->SetFontGlyphSet( m_FontAliases[i]._font, fontdata->GetString( "name" ),
fontTall, fontdata->GetInt( "weight" ), blur, scanlines, flags);
}
}
// don't add any more
break;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUIScheme::SpewFonts( void )
{
Msg( "Game UI Scheme: %s (%s)\n", GetName(), GetFileName() );
for ( int i = 0; i < m_FontAliases.Count(); i++ )
{
Msg( " %2d: HFont:0x%8.8x, %s, %s, font:%s, tall:%d\n",
i,
m_FontAliases[i]._font,
m_FontAliases[i]._trueFontName.String(),
m_FontAliases[i]._fontName.String(),
g_pGameUISystemSurface->GetFontName( m_FontAliases[i]._font ),
g_pGameUISystemSurface->GetFontTall( m_FontAliases[i]._font ) );
}
}
//-----------------------------------------------------------------------------
// Purpose: Kills the scheme
//-----------------------------------------------------------------------------
void CGameUIScheme::Shutdown( bool full )
{
SetActive( false );
m_FontRanges.RemoveAll();
if (m_pData)
{
m_pData->deleteThis();
m_pData = NULL;
}
if ( full )
{
delete this;
}
}
//-----------------------------------------------------------------------------
// Finds a font in the alias list
//-----------------------------------------------------------------------------
FontHandle_t CGameUIScheme::FindFontInAliasList( const char *fontName )
{
// FIXME: Slow!!!
for (int i = m_FontAliases.Count(); --i >= 0; )
{
if ( !strnicmp( fontName, m_FontAliases[i]._fontName.String(), FONT_ALIAS_NAME_LENGTH ) )
return m_FontAliases[i]._font;
}
// No dice
return 0;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : font -
// Output : char const
//-----------------------------------------------------------------------------
char const *CGameUIScheme::GetFontName( const FontHandle_t &font )
{
for (int i = m_FontAliases.Count(); --i >= 0; )
{
FontHandle_t fnt = ( FontHandle_t )m_FontAliases[i]._font;
if ( fnt == font )
return m_FontAliases[i]._trueFontName.String();
}
return "<Unknown font>";
}
//-----------------------------------------------------------------------------
// material Setting methods
//-----------------------------------------------------------------------------
FontHandle_t CGameUIScheme::GetFont( const char *fontName, bool proportional )
{
// First look in the list of aliases...
return FindFontInAliasList( GetMungedFontName( fontName, m_pTag.Get(), proportional ) );
}
//-----------------------------------------------------------------------------
// Return the vgui name of the font that is the same truefont name and one size up.
// bUp is if true you want the next size up or the next size down.
//-----------------------------------------------------------------------------
FontHandle_t CGameUIScheme::GetFontNextSize( bool bUp, const char *fontName, bool proportional )
{
FontHandle_t currentFontHandle = GetFont( fontName, proportional );
// Current font name wasn't found.
if ( currentFontHandle == 0 )
{
return currentFontHandle;
}
int currentFontTall = g_pGameUISystemSurface->GetFontTall( currentFontHandle );
const char* pCurrentFontName = g_pGameUISystemSurface->GetFontName( currentFontHandle );
// Now find the closest font with this name that is the smallest size up
int sizeDifference = INT_MAX;
FontHandle_t closestFontHandle = 0;
for (int i = m_FontAliases.Count(); --i > 0; )
{
if ( proportional != m_FontAliases[i].m_bProportional )
continue;
FontHandle_t testFontHandle = m_FontAliases[i]._font;
const char* pTestFontName = g_pGameUISystemSurface->GetFontName( testFontHandle );
if ( currentFontHandle != testFontHandle )
{
if ( !Q_stricmp( pCurrentFontName, pTestFontName ) ) // font name is the same.
{
int thisFontTall = g_pGameUISystemSurface->GetFontTall( testFontHandle );
int diff;
if ( bUp ) // get next size up
{
diff = thisFontTall - currentFontTall;
}
else // get next size down.
{
diff = currentFontTall - thisFontTall;
}
if ( diff > 0 && diff < sizeDifference )
{
sizeDifference = diff;
closestFontHandle = testFontHandle;
}
}
}
}
if ( closestFontHandle != 0 )
{
return closestFontHandle;
}
else
{
return currentFontHandle;
}
}
//-----------------------------------------------------------------------------
// Purpose: returns a char string of the munged name this font is stored as in the font manager
//-----------------------------------------------------------------------------
const char *CGameUIScheme::GetMungedFontName( const char *fontName, const char *scheme, bool proportional )
{
static char mungeBuffer[ 64 ];
if ( scheme )
{
Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s%s-%s", fontName, scheme, proportional ? "p" : "no" );
}
else
{
Q_snprintf( mungeBuffer, sizeof( mungeBuffer ), "%s-%s", fontName, proportional ? "p" : "no" ); // we don't want the "(null)" snprintf appends
}
return mungeBuffer;
}
//-----------------------------------------------------------------------------
// Purpose: gets the minimum font height for the current language
//-----------------------------------------------------------------------------
int CGameUIScheme::GetMinimumFontHeightForCurrentLanguage( const char *pLanguage )
{
char language[64];
bool bValid;
if ( IsPC() )
{
if ( pLanguage )
{
Q_strncpy( language, pLanguage, sizeof(language)-1 );
bValid = true;
}
else
{
bValid = vgui::system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", language, sizeof(language)-1 );
}
}
else
{
Q_strncpy( language, XBX_GetLanguageString(), sizeof( language ) );
bValid = true;
}
if ( bValid )
{
if (!stricmp(language, "korean")
|| !stricmp(language, "koreana")
|| !stricmp(language, "tchinese")
|| !stricmp(language, "schinese")
|| !stricmp(language, "japanese"))
{
// the bitmap-based fonts for these languages simply don't work with a pt. size of less than 9 (13 pixels)
return 13;
}
if ( !stricmp(language, "thai" ) )
{
// thai has problems below 18 pts
return 18;
}
}
// no special minimum height required
return 0;
}
void CGameUIScheme::SetActive( bool bActive )
{
m_bActive = bActive;
}
bool CGameUIScheme::IsActive() const
{
return m_bActive;
}

View File

@@ -0,0 +1,160 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEUISCHEME_H
#define GAMEUISCHEME_H
#ifdef _WIN32
#pragma once
#endif
#include "igameuisystemmgr.h"
#include "vgui_surfacelib/ifontsurface.h"
#include "tier1/utlstring.h"
//#include "color.h"
#include "tier1/utlsymbol.h"
class CGameUISystemSurface;
class KeyValues;
//-----------------------------------------------------------------------------
// Game UI version of a vgui scheme
//-----------------------------------------------------------------------------
class CGameUIScheme : public IGameUIScheme
{
public:
CGameUIScheme();
~CGameUIScheme();
FontHandle_t GetFont( const char *fontName, bool proportional = false );
FontHandle_t GetFontNextSize( bool bUp, const char *fontName, bool proportional = false );
//Color GetColor( const char *colorName, Color defaultColor ){ return Color( 255, 255, 255, 255 ); }
// These fxns are very similar to CScheme.
void Shutdown( bool full );
void LoadFromFile( const char *pFilename, const char *inTag, KeyValues *inKeys );
// Gets at the scheme's name
const char *GetName() { return m_pTag; }
const char *GetFileName() { return m_pFileName; }
char const *GetFontName( const FontHandle_t &font );
void ReloadFontGlyphs( int inScreenTall = -1 );
void SpewFonts();
bool GetFontRange( const char *fontname, int &nMin, int &nMax );
void SetFontRange( const char *fontname, int nMin, int nMax );
void SetActive( bool bActive );
bool IsActive() const;
private:
const char *GetMungedFontName( const char *fontName, const char *scheme, bool proportional );
void LoadFonts();
int GetMinimumFontHeightForCurrentLanguage( const char *pLanguage = NULL );
FontHandle_t FindFontInAliasList( const char *fontName );
bool m_bActive;
CUtlString m_pFileName;
CUtlString m_pTag;
KeyValues *m_pData;
#pragma pack(1)
struct fontalias_t
{
CUtlSymbol _fontName;
CUtlSymbol _trueFontName;
unsigned short _font : 15;
unsigned short m_bProportional : 1;
};
#pragma pack()
struct fontrange_t
{
CUtlSymbol _fontName;
int _min;
int _max;
};
CUtlVector< fontrange_t > m_FontRanges;
CUtlVector< fontalias_t > m_FontAliases;
};
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
class CGameUISchemeManager : public IGameUISchemeMgr
{
public:
CGameUISchemeManager();
~CGameUISchemeManager();
// loads a scheme from a file
// first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that
// tag is friendly string representing the name of the loaded scheme
IGameUIScheme * LoadSchemeFromFile( const char *fileName, const char *tag );
// reloads the schemes from the file
void ReloadSchemes();
// reloads scheme fonts
void ReloadFonts( int inScreenTall = -1 );
// returns a handle to the default (first loaded) scheme
IGameUIScheme * GetDefaultScheme();
// returns a handle to the scheme identified by "tag"
IGameUIScheme * GetScheme( const char *tag );
void Shutdown( bool full );
// gets the proportional coordinates for doing screen-size independant panel layouts
// use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
int GetProportionalScaledValue( int normalizedValue, int screenTall = -1 );
int GetProportionalNormalizedValue( int scaledValue ){ return 1; }
// first scheme loaded becomes the default scheme, and all subsequent loaded scheme are derivitives of that
IGameUIScheme * LoadSchemeFromFileEx( const char *pFilename, const char *tag );
// gets the proportional coordinates for doing screen-size independant panel layouts
// use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
int GetProportionalScaledValueEx( IGameUIScheme * scheme, int normalizedValue, int screenTall = -1 ){ return 0; }
int GetProportionalNormalizedValueEx( IGameUIScheme * scheme, int scaledValue ){ return 0; }
// gets the proportional coordinates for doing screen-size independant panel layouts
// use these for font, image and panel size scaling (they all use the pixel height of the display for scaling)
int GetProportionalScaledValueEx( CGameUIScheme *pScheme, int normalizedValue, int screenTall = -1 );
int GetProportionalNormalizedValueEx( CGameUIScheme *pScheme, int scaledValue );
void SpewFonts();
void SetLanguage( const char *pLanguage );
const char *GetLanguage();
private:
int GetProportionalScaledValue_( int screenTall, int normalizedValue );
// Search for already-loaded schemes
IGameUIScheme * FindLoadedScheme(const char *pFilename);
CUtlVector< CGameUIScheme * > m_Schemes;
};
extern CGameUISchemeManager *g_pGameUISchemeManager;
#endif // GAMEUISCHEME_H

View File

@@ -0,0 +1,225 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#include "tier0/dbg.h"
#include "gameuiscript.h"
#include "gameuiscriptinterface.h"
#include "gameuidefinition.h"
#include "keyvalues.h"
#include "fmtstr.h"
static ConVar ui_script_error_path( "ui_script_error_path", "", FCVAR_DEVELOPMENTONLY );
//-------------------------------------------------------------
//
//-------------------------------------------------------------
static void ScriptOutputFunc( const char *pszText )
{
Msg( "%s\n", pszText );
}
//-------------------------------------------------------------
//
//-------------------------------------------------------------
static bool ScriptErrorFunc( ScriptErrorLevel_t eLevel, const char *pszText )
{
// Attempt to parse the error for Visual Studio presentation for double-click
if ( char const *pParse1 = StringAfterPrefix( pszText, "[string \"" ) )
{
if ( char const *pQuote = strchr( pParse1, '\"' ) )
{
if ( char const *pParse2 = StringAfterPrefix( pQuote, "\"]:" ) )
{
if ( char const *pEndNum = strchr( pParse2, ':' ) )
{
char const *szType = (eLevel == SCRIPT_LEVEL_WARNING) ? "WARNING" : "ERROR";
Warning( "%s%.*s(%.*s): %s: %s\n",
ui_script_error_path.GetString(),
pQuote - pParse1, pParse1, // file name
pEndNum - pParse2, pParse2, // line number
szType,
pEndNum + 1
);
return true;
}
}
}
}
switch( eLevel )
{
case SCRIPT_LEVEL_WARNING:
Warning( "WARNING: %s\n", pszText );
break;
case SCRIPT_LEVEL_ERROR:
Warning( "ERROR: %s\n", pszText );
break;
}
return true;
}
//-------------------------------------------------------------
// Constructor
//-------------------------------------------------------------
CGameUIScript::CGameUIScript( )
{
m_pScriptVM = GameUIScriptSystemCreate();
m_pScriptVM->SetOutputCallback( ScriptOutputFunc );
m_pScriptVM->SetErrorCallback( ScriptErrorFunc );
m_IsActive = false;
m_pGameUIScriptInterface = NULL;
m_Version = -1;
m_Name = "unknown";
}
//-------------------------------------------------------------
// Destructor
//-------------------------------------------------------------
CGameUIScript::~CGameUIScript( )
{
Shutdown();
}
void CGameUIScript::Shutdown()
{
if ( m_pGameUIScriptInterface )
{
delete m_pGameUIScriptInterface;
m_pGameUIScriptInterface = NULL;
}
}
//-------------------------------------------------------------
// Assign this class a script file and a menu to run it on
//-------------------------------------------------------------
bool CGameUIScript::SetScript( const char *pszFileName, CGameUIDefinition *pDef )
{
ScriptVariant_t Value;
m_ScriptFile = pszFileName;
m_pGameUIScriptInterface = new CGameUIScriptInterface( m_pScriptVM, pDef );
if ( GameUIScriptSystemRun( m_pScriptVM, m_ScriptFile, NULL, true ) == false )
{
return false;
}
if ( !m_pScriptVM->GetValue( pDef->GetName(), &Value ) )
{
return false;
}
m_Scope = Value.m_hScript;
// we don't release Value as that would kill m_Scope.
//GetScriptName();
GetScriptVersion();
#ifndef _DEBUG
//if ( m_Version != build_number() && 0 )
//{
// Msg( "Script %s is out of date. Got %d. Expected %d.\n", pszFileName, m_Version, build_number() );
// return false;
//}
#endif
return true;
}
//-------------------------------------------------------------
//
//-------------------------------------------------------------
bool CGameUIScript::GetScriptName( )
{
HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( "Name", m_Scope );
if ( ExecuteFuncProc == NULL )
{
return false;
}
ScriptVariant_t Return;
m_pScriptVM->Call( ExecuteFuncProc, m_Scope, true, &Return );
m_Name = Return.m_pszString;
m_pScriptVM->ReleaseFunction( ExecuteFuncProc );
m_pScriptVM->ReleaseValue( Return );
return true;
}
//-------------------------------------------------------------
//
//-------------------------------------------------------------
bool CGameUIScript::GetScriptVersion( )
{
HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( "Version", m_Scope );
if ( ExecuteFuncProc == NULL )
{
return false;
}
ScriptVariant_t Return;
m_pScriptVM->Call( ExecuteFuncProc, m_Scope, true, &Return );
if ( Return.m_type == FIELD_FLOAT )
{
m_Version = ( int )Return.m_float;
}
else
{
m_Version = Return.m_int;
}
m_pScriptVM->ReleaseFunction( ExecuteFuncProc );
m_pScriptVM->ReleaseValue( Return );
return true;
}
//-------------------------------------------------------------
// Call a scripting function that takes an array of strings as an arg.
//-------------------------------------------------------------
bool CGameUIScript::Execute( KeyValues *pData, KeyValues **ppResult )
{
const char *eventName = pData->GetName();
HSCRIPT ExecuteFuncProc = m_pScriptVM->LookupFunction( eventName, m_Scope );
if ( ExecuteFuncProc == NULL )
{
return false;
}
// Transform the key values into script scope to execute
HSCRIPT hParams = CGameUIScriptInterface::ScriptTableFromKeyValues( m_pScriptVM, pData );
ScriptVariant_t varParams = hParams, varResult;
ScriptStatus_t ret = m_pScriptVM->ExecuteFunction( ExecuteFuncProc, &varParams, 1, &varResult, m_Scope, true );
if ( hParams )
{
m_pScriptVM->ReleaseValue( varParams );
}
if ( ret == SCRIPT_DONE && varResult.m_type == FIELD_HSCRIPT && ppResult )
{
Assert( !*ppResult ); // storing return value, might overwrite caller's keyvalues
*ppResult = CGameUIScriptInterface::ScriptVmKeyValueFromVariant( m_pScriptVM, varResult );
}
m_pScriptVM->ReleaseValue( varResult );
m_pScriptVM->ReleaseFunction( ExecuteFuncProc );
return true;
}

View File

@@ -0,0 +1,57 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines gameui scripting system.
//
//===========================================================================//
#ifndef GAMEUISCRIPT_H
#define GAMEUISCRIPT_H
#ifdef _WIN32
#pragma once
#endif
#include "gameuiscriptsystem.h"
class CGameUIScriptInterface;
class CGameUIDefinition;
class KeyValues;
class CGameUIScript
{
public:
CGameUIScript( );
~CGameUIScript( );
void Shutdown();
IScriptVM *GetVM( ) { return m_pScriptVM; }
CUtlString &GetName( ) { return m_Name; }
int GetVersion( ) { return m_Version; }
CUtlString &GetScriptFile( ) { return m_ScriptFile; }
bool IsActive( ) { return m_IsActive; }
bool SetScript( const char *pszFileName, CGameUIDefinition *pDef );
void SetActive( bool IsActive ) { m_IsActive = IsActive; }
bool Execute( KeyValues *pData, KeyValues **ppResult );
CGameUIScriptInterface * GetScriptInterface() const { return m_pGameUIScriptInterface; }
private:
bool GetScriptName( );
bool GetScriptType( );
bool GetScriptVersion( );
CGameUIScriptInterface *m_pGameUIScriptInterface;
CUtlString m_Name;
int m_Version;
bool m_IsActive;
CUtlString m_ScriptFile;
IScriptVM *m_pScriptVM;
HSCRIPT m_Scope;
};
#endif // GAMEUISCRIPT_H

View File

@@ -0,0 +1,565 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#include "gameuiscriptInterface.h"
#include "gameuisystemmgr.h"
#include "gameuidefinition.h"
#include "gamelayer.h"
#include "gamegraphic.h"
#include "fmtstr.h"
#include "gameuiscript.h"
#include "gameuisystem.h"
#include "gametext.h"
#include "dynamicrect.h"
#include "tier2/tier2.h"
#include "matchmaking/imatchframework.h"
BEGIN_SCRIPTDESC_ROOT_NAMED( CGameUIScriptInterface, "CGameUIScriptInterface", SCRIPT_SINGLETON "" )
// HSCRIPT table-kv functions
DEFINE_SCRIPTFUNC( LoadMenu, "LoadMenu( name, {params} ) : Load a menu." )
DEFINE_SCRIPTFUNC( CreateGraphic, "CreateGraphic( classname, {params} ) : Create a graphic." )
DEFINE_SCRIPTFUNC( CallScript, "CallScript( scripthandle, function, {params} ) : Execute other script function (scripthandle=0 will run local script)." )
DEFINE_SCRIPTFUNC( CallGraphic, "CallGraphic( graphichandle, commandname, {params} ) : Execute a graphic function." )
DEFINE_SCRIPTFUNC( Nugget, "Nugget( action, {params} ) : Interface with nuggets." )
END_SCRIPTDESC()
static ConVar ui_script_spew_level( "ui_script_spew_level", 0, FCVAR_DEVELOPMENTONLY );
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameUIScriptInterface::CGameUIScriptInterface( IScriptVM *pScriptVM, CGameUIDefinition *pDef ) :
m_Nuggets( UtlStringLessFunc ),
m_GraphicScriptInstances( UtlStringLessFunc ),
m_pScriptVM( pScriptVM ),
m_pMenu( pDef )
{
m_Scope = m_pScriptVM->RegisterInstance( this, "c" );
}
CGameUIScriptInterface::~CGameUIScriptInterface()
{
Shutdown();
}
void CGameUIScriptInterface::Shutdown()
{
// Unload all nuggets
for ( unsigned short k = m_Nuggets.FirstInorder(); k != m_Nuggets.InvalidIndex(); k = m_Nuggets.NextInorder( k ) )
{
IGameUIScreenController *pNugget = m_Nuggets.Element( k );
pNugget->OnScreenDisconnected( m_pMenu->GetGameUISystem() );
}
m_Nuggets.Purge();
}
//-----------------------------------------------------------------------------
// Show the ID menu next frame, and hide this menu next frame.
//-----------------------------------------------------------------------------
HSCRIPT CGameUIScriptInterface::LoadMenu( const char *szMenuName, HSCRIPT hParams )
{
if ( !szMenuName || !*szMenuName )
return NULL;
// Build the key values for the command and broadcast (deleted inside broadcast system)
KeyValues *kvCommand = ScriptTableToKeyValues( m_pScriptVM, szMenuName, hParams );
KeyValues::AutoDelete autodelete_kvCommand( kvCommand );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "CGameUIScriptInterface::LoadMenu\n" );
KeyValuesDumpAsDevMsg( kvCommand );
}
IGameUISystem *pUI = g_pGameUISystemMgrImpl->LoadGameUIScreen( kvCommand );
if ( !pUI )
return NULL;
KeyValues *kvResult = new KeyValues( "" );
KeyValues::AutoDelete autodelete_kvResult( kvResult );
kvResult->SetInt( "scripthandle", pUI->GetScriptHandle() );
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
HSCRIPT CGameUIScriptInterface::CreateGraphic( const char *szGraphicClassName, HSCRIPT hParams )
{
if ( !szGraphicClassName || !*szGraphicClassName )
return NULL;
if ( !m_pMenu || !m_pMenu->GetGameUISystem() )
{
DevWarning( "Scripts not connected to game UI system and cannot create graphics!\n" );
return NULL;
}
// Build the key values for the command
KeyValues *kvCommand = ScriptTableToKeyValues( m_pScriptVM, szGraphicClassName, hParams );
KeyValues::AutoDelete autodelete_kvCommand( kvCommand );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "CGameUIScriptInterface::CreateGraphic\n" );
KeyValuesDumpAsDevMsg( kvCommand );
}
const char* szGraphicName = kvCommand->GetString( "name", NULL );
// Check if this instance is already created
if ( szGraphicName == NULL )
{
DevWarning( "A must have a name!\n", szGraphicName );
return NULL;
}
// Check if an instance of this graphic already exists
CGameGraphic *pGraphic = m_pMenu->GraphicExists( szGraphicName );
if ( pGraphic )
{
DevWarning( "A graphic with this name %s is already loaded!\n", szGraphicName );
return NULL;
}
IGameUIGraphicClassFactory *pFactory = g_pGameUISystemMgrImpl->GetGraphicClassFactory( szGraphicClassName );
if ( !pFactory )
{
DevWarning( "No graphic class factory for %s!\n", szGraphicClassName );
return NULL;
}
CGameGraphic *pNewGraphic = pFactory->CreateNewGraphicClass( kvCommand, m_pMenu );
if ( !pNewGraphic )
{
DevWarning( "No graphic in factory %s!\n", szGraphicClassName );
return NULL;
}
KeyValues *kvResult = new KeyValues( "" );
KeyValues::AutoDelete autodelete_kvResult( kvResult );
kvResult->SetInt( "scripthandle", pNewGraphic->GetScriptHandle() );
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
HSCRIPT CGameUIScriptInterface::CallScript( int32 iScriptHandle, const char *szCommandName, HSCRIPT hParams )
{
if ( !szCommandName || !*szCommandName )
return NULL;
// Try to resolve other script handle specified
CGameUISystem *pOtherScript = iScriptHandle ? CGameUISystem::FromScriptHandle( iScriptHandle ) : ( CGameUISystem * ) m_pMenu->GetGameUISystem();
if ( !pOtherScript )
{
Warning( "CGameUIScriptInterface::CallScript with invalid script handle %d!\n", iScriptHandle );
return NULL;
}
// Build the key values for the command and call other script
KeyValues *kvCommand = ScriptTableToKeyValues( m_pScriptVM, szCommandName, hParams );
KeyValues::AutoDelete autodelete_kvCommand( kvCommand );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "CGameUIScriptInterface::CallScript( %d : %s )\n", iScriptHandle, pOtherScript->GetName() );
KeyValuesDumpAsDevMsg( kvCommand );
}
// Pass the command to another script
KeyValues *kvResult = NULL;
pOtherScript->ExecuteScript( kvCommand, &kvResult );
if ( ui_script_spew_level.GetInt() > 0 )
{
KeyValuesDumpAsDevMsg( kvResult );
}
KeyValues::AutoDelete autodelete_kvResult( kvResult );
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
HSCRIPT CGameUIScriptInterface::CallGraphic( int32 iGraphicHandle, const char *szCommandName, HSCRIPT hParams )
{
if ( !szCommandName || !*szCommandName || !iGraphicHandle )
return NULL;
CGameGraphic *pGraphic = CGameGraphic::FromScriptHandle( iGraphicHandle );
if ( !pGraphic )
{
Warning( "CGameUIScriptInterface::CallGraphic with invalid graphic handle %d!\n", iGraphicHandle );
return NULL;
}
// Build the key values for the command and call other script
KeyValues *kvCommand = ScriptTableToKeyValues( m_pScriptVM, szCommandName, hParams );
KeyValues::AutoDelete autodelete_kvCommand( kvCommand );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "CGameUIScriptInterface::CallGraphic( %d : %s )\n", iGraphicHandle, pGraphic->GetName() );
KeyValuesDumpAsDevMsg( kvCommand );
}
// Pass the command to graphic
KeyValues *kvResult = pGraphic->HandleScriptCommand( kvCommand);
if ( ui_script_spew_level.GetInt() > 0 )
{
KeyValuesDumpAsDevMsg( kvResult );
}
KeyValues::AutoDelete autodelete_kvResult( kvResult );
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
HSCRIPT CGameUIScriptInterface::Nugget( const char *szCommandName, HSCRIPT hParams )
{
if ( !szCommandName || !*szCommandName )
return NULL;
if ( !m_pMenu || !m_pMenu->GetGameUISystem() )
{
DevWarning( "Scripts not connected to game UI system and cannot use nuggets!\n" );
return NULL;
}
// Build the key values for the command
KeyValues *kvCommand = ScriptTableToKeyValues( m_pScriptVM, szCommandName, hParams );
KeyValues::AutoDelete autodelete_kvCommand( kvCommand );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "CGameUIScriptInterface::Nugget\n" );
KeyValuesDumpAsDevMsg( kvCommand );
}
// Parse the command
if ( char const *szUseName = StringAfterPrefix( kvCommand->GetName(), "load:" ) )
{
char const *szNuggetName = szUseName;
szUseName = kvCommand->GetString( "usename", szNuggetName );
// Check if the nugget is already loaded
if ( m_Nuggets.Find( szUseName ) != m_Nuggets.InvalidIndex() )
{
DevWarning( "Nugget factory %s is already loaded!\n", szUseName );
return NULL;
}
IGameUIScreenControllerFactory *pFactory = g_pGameUISystemMgrImpl->GetScreenControllerFactory( szNuggetName );
if ( !pFactory )
{
DevWarning( "No nugget factory for %s!\n", szNuggetName );
return NULL;
}
kvCommand->SetName( szNuggetName );
IGameUIScreenController *pNugget = pFactory->GetController( kvCommand );
if ( !pNugget )
{
DevWarning( "No nugget in factory %s!\n", szNuggetName );
return NULL;
}
// Connect the nugget with our screen
m_Nuggets.Insert( szUseName, pNugget );
pNugget->OnScreenConnected( m_pMenu->GetGameUISystem() );
KeyValues *kvResult = new KeyValues( "" );
KeyValues::AutoDelete autodelete_kvResult( kvResult );
kvResult->SetInt( "scripthandle", m_pMenu->GetGameUISystem()->GetScriptHandle() );
kvResult->SetString( "usename", szUseName );
kvResult->SetInt( "ptr", reinterpret_cast< int >( pNugget ) );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "Loaded nugget %s\n", szNuggetName );
KeyValuesDumpAsDevMsg( kvResult );
}
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
if ( char const *szUseName = StringAfterPrefix( kvCommand->GetName(), "ref:" ) )
{
int iRefScriptHandle = kvCommand->GetInt( "scripthandle" );
char const *szRefUseName = kvCommand->GetString( "usename", szUseName );
// Check if the nugget is already loaded
if ( m_Nuggets.Find( szUseName ) != m_Nuggets.InvalidIndex() )
{
DevWarning( "Nugget factory %s is already loaded!\n", szUseName );
return NULL;
}
CGameUISystem *pMenu = iRefScriptHandle ? CGameUISystem::FromScriptHandle( iRefScriptHandle ) : ( CGameUISystem * ) m_pMenu->GetGameUISystem();
if ( !pMenu )
{
DevWarning( "Nugget reference request %s with invalid script handle %d!\n", szUseName, iRefScriptHandle );
return NULL;
}
CGameUIScriptInterface *pRefInterface = NULL;
if ( CGameUIScript *pScript = pMenu->Definition().GetScript() )
pRefInterface = pScript->GetScriptInterface();
if ( !pRefInterface )
{
DevWarning( "Nugget reference request %s with script handle %d(%s) which has no scripts!\n", szUseName, iRefScriptHandle, pMenu->GetName() );
return NULL;
}
unsigned short usIdx = pRefInterface->m_Nuggets.Find( szRefUseName );
if ( usIdx == pRefInterface->m_Nuggets.InvalidIndex() )
{
DevWarning( "Nugget reference request %s with script handle %d(%s) which has no nugget %s!\n", szUseName, iRefScriptHandle, pMenu->GetName(), szRefUseName );
return NULL;
}
IGameUIScreenController *pNugget = pRefInterface->m_Nuggets.Element( usIdx );
if ( reinterpret_cast< int >( pNugget ) != kvCommand->GetInt( "ptr" ) )
{
DevWarning( "Nugget reference request %s with script handle %d(%s) for nugget %s yielding %08X instead of expected %08X!\n",
szUseName, iRefScriptHandle, pMenu->GetName(), szRefUseName, reinterpret_cast< int >( pNugget ), kvCommand->GetInt( "ptr" ) );
}
// Connect the nugget with our screen
m_Nuggets.Insert( szUseName, pNugget );
pNugget->OnScreenConnected( m_pMenu->GetGameUISystem() );
KeyValues *kvResult = new KeyValues( "" );
KeyValues::AutoDelete autodelete_kvResult( kvResult );
kvResult->SetInt( "scripthandle", m_pMenu->GetGameUISystem()->GetScriptHandle() );
kvResult->SetString( "usename", szUseName );
kvResult->SetInt( "ptr", reinterpret_cast< int >( pNugget ) );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "Referenced nugget %s from %d(%s):%s\n", szUseName, iRefScriptHandle, pMenu->GetName(), szRefUseName );
KeyValuesDumpAsDevMsg( kvResult );
}
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
if ( char const *szUseName = StringAfterPrefix( kvCommand->GetName(), "free:" ) )
{
// Check if the nugget is already loaded
unsigned short usIdx = m_Nuggets.Find( szUseName );
if ( usIdx == m_Nuggets.InvalidIndex() )
{
DevWarning( "Nugget factory %s is not loaded!\n", szUseName );
return NULL;
}
// Unload the nugget
IGameUIScreenController *pNugget = m_Nuggets.Element( usIdx );
m_Nuggets.RemoveAt( usIdx );
pNugget->OnScreenDisconnected( m_pMenu->GetGameUISystem() );
if ( ui_script_spew_level.GetInt() > 0 )
{
DevMsg( "Unloaded nugget %s\n", szUseName );
}
return NULL;
}
if ( char const *szUse = StringAfterPrefix( kvCommand->GetName(), "use:" ) )
{
char const *szUseName = szUse;
// Split off nugget name by :
if ( char const *pch = strchr( szUseName, ':' ) )
{
char *buf = ( char * ) stackalloc( pch - szUseName + 1 );
Q_strncpy( buf, szUseName, pch - szUseName + 1 );
szUseName = buf;
kvCommand->SetName( pch + 1 );
}
else
{
kvCommand->SetName( "" );
}
// Check if the nugget is already loaded
unsigned short usIdx = m_Nuggets.Find( szUseName );
if ( usIdx == m_Nuggets.InvalidIndex() )
{
DevWarning( "Nugget factory %s is not loaded!\n", szUseName );
return NULL;
}
// Nugget operation
IGameUIScreenController *pNugget = m_Nuggets.Element( usIdx );
KeyValues *kvResult = pNugget->OnScreenEvent( m_pMenu->GetGameUISystem(), kvCommand );
KeyValues::AutoDelete autodelete_kvResult( kvResult );
if ( ui_script_spew_level.GetInt() > 0 )
{
KeyValuesDumpAsDevMsg( kvResult );
}
// Push results for the script
return ScriptTableFromKeyValues( m_pScriptVM, kvResult );
}
return NULL;
}
bool CGameUIScriptInterface::ScriptVmKeyValueToVariant( IScriptVM *pVM, KeyValues *val, ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] )
{
switch ( val->GetDataType() )
{
case KeyValues::TYPE_STRING:
varValue = val->GetString();
return true;
case KeyValues::TYPE_INT:
varValue = val->GetInt();
return true;
case KeyValues::TYPE_FLOAT:
varValue = val->GetFloat();
return true;
case KeyValues::TYPE_UINT64:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%llu", val->GetUint64() );
varValue = chScratchBuffer;
return true;
case KeyValues::TYPE_NONE:
varValue = ScriptTableFromKeyValues( pVM, val );
return true;
default:
Warning( "ScriptVmKeyValueToVariant failed to package parameter %s (type %d)\n", val->GetName(), val->GetDataType() );
return false;
}
}
bool CGameUIScriptInterface::ScriptVmStringFromVariant( ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] )
{
switch ( varValue.m_type )
{
case FIELD_INTEGER:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%d", varValue.m_int );
return true;
case FIELD_FLOAT:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%f", varValue.m_float );
return true;
case FIELD_BOOLEAN:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%d", varValue.m_bool );
return true;
case FIELD_CHARACTER:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%c", varValue.m_char );
return true;
case FIELD_CSTRING:
Q_snprintf( chScratchBuffer, KV_VARIANT_SCRATCH_BUF_SIZE, "%s", varValue.m_pszString ? varValue.m_pszString : "" );
return true;
default:
Warning( "ScriptVmStringFromVariant failed to unpack parameter variant type %d\n", varValue.m_type );
return false;
}
}
KeyValues * CGameUIScriptInterface::ScriptVmKeyValueFromVariant( IScriptVM *pVM, ScriptVariant_t &varValue )
{
KeyValues *val = NULL;
switch ( varValue.m_type )
{
case FIELD_INTEGER:
val = new KeyValues( "" );
val->SetInt( NULL, varValue.m_int );
return val;
case FIELD_FLOAT:
val = new KeyValues( "" );
val->SetFloat( NULL, varValue.m_float );
return val;
case FIELD_BOOLEAN:
val = new KeyValues( "" );
val->SetInt( NULL, varValue.m_bool ? 1 : 0 );
return val;
case FIELD_CHARACTER:
val = new KeyValues( "" );
val->SetString( NULL, CFmtStr( "%c", varValue.m_char ) );
return val;
case FIELD_CSTRING:
val = new KeyValues( "" );
val->SetString( NULL, varValue.m_pszString ? varValue.m_pszString : "" );
return val;
case FIELD_HSCRIPT:
return ScriptTableToKeyValues( pVM, "", varValue.m_hScript );
default:
Warning( "ScriptVmKeyValueFromVariant failed to unpack parameter variant type %d\n", varValue.m_type );
return NULL;
}
}
KeyValues * CGameUIScriptInterface::ScriptTableToKeyValues( IScriptVM *pVM, char const *szName, HSCRIPT hTable )
{
if ( !szName )
szName = "";
KeyValues *kv = new KeyValues( szName );
if ( hTable && pVM )
{
int numKeys = pVM->GetNumTableEntries( hTable );
for ( int k = 0; k < numKeys; ++ k )
{
ScriptVariant_t varKey, varValue;
pVM->GetKeyValue( hTable, k, &varKey, &varValue );
char chScratchBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ];
if ( !ScriptVmStringFromVariant( varKey, chScratchBuffer ) )
{
Assert( 0 );
continue;
}
KeyValues *sub = ScriptVmKeyValueFromVariant( pVM, varValue );
if ( !sub )
{
Assert( 0 );
// sub->deleteThis();
// continue;
// still proceed - it will be a key with no data
sub = new KeyValues( "" );
}
sub->SetName( chScratchBuffer );
kv->AddSubKey( sub );
}
}
return kv;
}
HSCRIPT CGameUIScriptInterface::ScriptTableFromKeyValues( IScriptVM *pVM, KeyValues *kv )
{
if ( !kv || !pVM )
return NULL;
ScriptVariant_t varTable;
pVM->CreateTable( varTable );
for ( KeyValues *val = kv->GetFirstSubKey(); val; val = val->GetNextKey() )
{
ScriptVariant_t varValue;
char chScratchBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ];
if ( !ScriptVmKeyValueToVariant( pVM, val, varValue, chScratchBuffer ) )
continue;
#ifdef GAMEUI_SCRIPT_LOWERCASE_ALL_TABLE_KEYS
char chNameBuffer[ KV_VARIANT_SCRATCH_BUF_SIZE ];
Q_strncpy( chNameBuffer, val->GetName(), KV_VARIANT_SCRATCH_BUF_SIZE );
Q_strlower( chNameBuffer );
#else
char const *chNameBuffer = val->GetName();
#endif
pVM->SetValue( varTable.m_hScript, chNameBuffer, varValue );
}
return varTable.m_hScript;
}

View File

@@ -0,0 +1,71 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#ifndef GAMEUISCRIPTINTERFACE_H
#define GAMEUISCRIPTINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "game_controls/igameuisystemmgr.h"
#include "gameuiscriptsystem.h"
#include "tier1/utlntree.h"
#include "utlmap.h"
class CGameUIDefinition;
class CGameGraphic;
//-----------------------------------------------------------------------------
// These are functions that can be called from lua that do things in the gameui.
//-----------------------------------------------------------------------------
class CGameUIScriptInterface
{
public:
explicit CGameUIScriptInterface( IScriptVM *pScriptVM, CGameUIDefinition *pDef );
~CGameUIScriptInterface();
int GetGraphicID( CGameGraphic *pGraphic );
public:
void Shutdown();
// Load a new menu to show now.
HSCRIPT LoadMenu( const char *szMenuName, HSCRIPT hParams );
// Create a graphic by classname
HSCRIPT CreateGraphic( const char *szGraphicClassName, HSCRIPT hParams );
// Execute a script command from menus
HSCRIPT CallScript( int32 iScriptHandle, const char *szCommandName, HSCRIPT hParams );
// Call a function inside a graphic
HSCRIPT CallGraphic( int32 iGraphicHandle, const char *szCommandName, HSCRIPT hParams );
// Interface with nuggets
HSCRIPT Nugget( const char *szCommandName, HSCRIPT hParams );
public:
enum { KV_VARIANT_SCRATCH_BUF_SIZE = 128 };
static bool ScriptVmKeyValueToVariant( IScriptVM *pVM, KeyValues *val, ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] );
static bool ScriptVmStringFromVariant( ScriptVariant_t &varValue, char chScratchBuffer[KV_VARIANT_SCRATCH_BUF_SIZE] );
static KeyValues * ScriptVmKeyValueFromVariant( IScriptVM *pVM, ScriptVariant_t &varValue );
static KeyValues * ScriptTableToKeyValues( IScriptVM *pVM, char const *szName, HSCRIPT hTable );
static HSCRIPT ScriptTableFromKeyValues( IScriptVM *pVM, KeyValues *kv );
private:
HSCRIPT m_Scope;
IScriptVM *m_pScriptVM;
CGameUIDefinition *m_pMenu;
CUtlMap< CUtlString, IGameUIScreenController * > m_Nuggets;
CUtlMap< CUtlString, CGameGraphic * > m_GraphicScriptInstances; // graphics created from scripting.
};
#endif // GAMEUISCRIPTINTERFACE_H

View File

@@ -0,0 +1,134 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#include "gameuiscriptsystem.h"
#include "tier1/utlbuffer.h"
#include "tier1/fmtstr.h"
#include "filesystem.h"
#include "gameuisystemmgr.h"
// memdbgon must be the last include file in a .cpp file!!!
#include <tier0/memdbgon.h>
IScriptVM *GameUIScriptSystemCreate( )
{
IScriptVM *pScriptVM = NULL;
ScriptLanguage_t scriptLanguage = SL_LUA;
if( scriptLanguage != SL_NONE )
{
pScriptVM = g_pScriptManager->CreateVM( scriptLanguage );
if( pScriptVM )
{
DevMsg("VSCRIPT: Started VScript virtual machine using script language '%s'\n", pScriptVM->GetLanguageName() );
char SZFullPath[ MAX_PATH ];
g_pFullFileSystem->RelativePathToFullPath( "scripts/vguiedit/modules", "GAME", SZFullPath, sizeof( SZFullPath ) );
pScriptVM->AddSearchPath( SZFullPath );
}
}
return pScriptVM;
}
HSCRIPT GameUIScriptSystemCompile( IScriptVM *pScriptVM, const char *pszScriptName, bool bWarnMissing )
{
if ( !pScriptVM )
{
return NULL;
}
static const char *pszExtensions[] =
{
"", // SL_NONE
".gm", // SL_GAMEMONKEY
".nut", // SL_SQUIRREL
".lua", // SL_LUA
".py", // SL_PYTHON
};
const char *pszVMExtension = pszExtensions[ pScriptVM->GetLanguage() ];
const char *pszIncomingExtension = V_strrchr( pszScriptName , '.' );
if ( pszIncomingExtension && V_stricmp( pszIncomingExtension, pszVMExtension ) != 0 )
{
Msg( "Script file type does not match VM type\n" );
return NULL;
}
CFmtStr scriptPath;
if ( pszIncomingExtension )
{
scriptPath.sprintf( "scripts/%s", pszScriptName );
}
else
{
scriptPath.sprintf( "scripts/%s%s", pszScriptName, pszVMExtension );
}
const char *pBase;
CUtlBuffer bufferScript;
if ( pScriptVM->GetLanguage() == SL_PYTHON )
{
// python auto-loads raw or precompiled modules - don't load data here
pBase = NULL;
}
else
{
bool bResult = g_pFullFileSystem->ReadFile( scriptPath, "GAME", bufferScript );
if( !bResult )
{
Warning( "Script not found (%s) \n", scriptPath.operator const char *() );
}
pBase = (const char *) bufferScript.Base();
if ( !pBase || !*pBase )
{
return NULL;
}
}
const char *pszFilename = V_strrchr( scriptPath, '/' );
pszFilename++;
HSCRIPT hScript = pScriptVM->CompileScript( pBase, pszFilename );
if ( hScript == INVALID_HSCRIPT )
{
DevMsg( "FAILED to compile and execute script file named %s\n", scriptPath.operator const char *() );
}
return hScript;
}
bool GameUIScriptSystemRun( IScriptVM *pScriptVM, const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing )
{
HSCRIPT hScript = GameUIScriptSystemCompile( pScriptVM, pszScriptName, bWarnMissing );
bool bSuccess = false;
if ( hScript != INVALID_HSCRIPT )
{
// if ( gpGlobals->maxClients == 1 )
//{
//CBaseEntity *pPlayer = UTIL_GetLocalPlayer();
//if ( pPlayer )
//{
//g_pScriptVM->SetValue( "player", pPlayer->GetScriptInstance() );
//}
//}
bSuccess = ( pScriptVM->Run( hScript, hScope ) != SCRIPT_ERROR );
if ( !bSuccess )
{
DevMsg( "Error running script named %s\n", pszScriptName );
}
pScriptVM->ReleaseScript( hScript );
}
return bSuccess;
}
#include <tier0/memdbgoff.h>

View File

@@ -0,0 +1,21 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose: Defines scripting system.
//
//===========================================================================//
#ifndef GAMEUISCRIPTSYSTEM_H
#define GAMEUISCRIPTSYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "vscript/ivscript.h"
IScriptVM *GameUIScriptSystemCreate();
HSCRIPT GameUIScriptSystemCompile( IScriptVM *pScriptVM, const char *pszScriptName, bool bWarnMissing );
bool GameUIScriptSystemRun( IScriptVM *pScriptVM, const char *pszScriptName, HSCRIPT hScope, bool bWarnMissing );
#endif // GAMEUISCRIPTSYSTEM_H

View File

@@ -0,0 +1,80 @@
//====== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. =======
//
// Purpose:
//
//=============================================================================
#ifndef GAMEUISYSTEM_H
#define GAMEUISYSTEM_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/timeutils.h"
#include "materialsystem/imaterialsystem.h"
#include "gameuidefinition.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IGameUIScreenController;
class CUtlBuffer;
class IRenderContext;
class IRenderDevice;
class KeyValues;
struct RenderViewport_t;
//-----------------------------------------------------------------------------
// Class to render a zillion ui elements
//-----------------------------------------------------------------------------
class CGameUISystem : public IGameUISystem
{
public:
CGameUISystem();
virtual ~CGameUISystem();
virtual char const * GetName();
virtual bool Init( KeyValues *kvLoadSettings );
virtual void Release();
virtual void Render( const Rect_t &viewport );
virtual void Render( IRenderContext *pRenderContext, const Rect_t &viewport );
virtual void LoadEmptyGameUI( const char *pName );
virtual bool LoadGameUIDefinition( CUtlBuffer &buf, const char *pFileName );
CGameUIDefinition &Definition() { return m_GameUIDef; }
virtual bool ExecuteScript( KeyValues *kvEvent, KeyValues **ppResult = NULL );
virtual void SetStageSize( int nWide, int nTall );
virtual void GetStageSize( Vector2D &stageSize );
virtual int32 GetScriptHandle() { return m_iScriptHandle; }
static CGameUISystem * FromScriptHandle( int32 iScriptHandle );
private:
void GenerateUIMesh( IMatRenderContext *pRenderContext, IMesh* pMesh, CUtlVector< CRenderGeometry > &renderGeometry, CSheet *pSheet );
void RenderStaticLayer( LayerRenderLists_t &renderList, int geometryIndex );
void RenderStaticLayer( IRenderContext *pRenderContext, LayerRenderLists_t &renderList, int geometryIndex );
void RenderDynamicLayer( LayerRenderLists_t &renderList, int geometryIndex );
void RenderTextLayer( CUtlVector< CRenderGeometry > &renderGeometry );
void RenderTextLayer( IRenderContext *pRenderContext, CUtlVector< CRenderGeometry > &renderGeometry );
CGameUIDefinition m_GameUIDef;
int32 m_iScriptHandle;
bool m_bDrawReport;
};
#endif // GAMEUISYSTEM_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,216 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef GAMEUISYSTEMMANAGER_H
#define GAMEUISYSTEMMANAGER_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
#include "tier1/timeutils.h"
#include "rendersystem/vertexdata.h"
#include "rendersystem/indexdata.h"
#include "inputsystem/buttoncode.h"
#include "gameuischeme.h"
#include "igameuisystemmgr.h"
#include "appframework/iappsystem.h"
#include "tier3/tier3dm.h"
#include "tier1/utlstring.h"
#include "tier1/utlmap.h"
#include "gameuidynamictextures.h"
//-----------------------------------------------------------------------------
// Forward declarations
//-----------------------------------------------------------------------------
class IGameUIScreenController;
class IRenderContext;
class CGameUISystem;
class CGameGraphic;
class CHitArea;
class CGameText;
class CGameUIDefinition;
FORWARD_DECLARE_HANDLE( InputContextHandle_t );
//-----------------------------------------------------------------------------
// Global interfaces...
//-----------------------------------------------------------------------------
class IScriptManager;
extern IScriptManager *g_pScriptManager;
abstract_class IGameUIGraphicClassFactory
{
public:
// Returns an instance of a graphic interface (keyvalues owned by caller)
virtual CGameGraphic * CreateNewGraphicClass( KeyValues *kvRequest, CGameUIDefinition *pMenu ) = 0;
};
//-----------------------------------------------------------------------------
//
// Game UI system manager
//
//-----------------------------------------------------------------------------
class CGameUISystemMgr : public CTier3AppSystem< IGameUISystemMgr >
{
typedef CTier3AppSystem< IGameUISystemMgr > BaseClass;
public:
// Constructor, destructor
CGameUISystemMgr();
virtual ~CGameUISystemMgr();
virtual bool Connect( CreateInterfaceFn factory );
virtual void Disconnect();
virtual const AppSystemInfo_t* GetDependencies();
virtual void *QueryInterface( const char *pInterfaceName );
virtual InitReturnVal_t Init( );
virtual void Shutdown();
virtual void SetGameUIVisible( bool bVisible );
virtual bool GetGameUIVisible(){ return IsMenuVisible(); }
// Load the game UI menu screen
// key values are owned and released by caller
virtual IGameUISystem * LoadGameUIScreen( KeyValues *kvScreenLoadSettings );
virtual void ReleaseAllGameUIScreens();
virtual void RunFrame();
virtual void RegisterScreenControllerFactory( char const *szControllerName, IGameUIScreenControllerFactory *pFactory );
virtual IGameUIScreenControllerFactory * GetScreenControllerFactory( char const *szControllerName );
virtual IGameUISystemSurface * GetSurface();
virtual IGameUISchemeMgr * GetSchemeMgr();
virtual IGameUIMiscUtils * GetMiscUtils();
virtual void Render( const Rect_t &viewport, DmeTime_t flCurrentTime );
virtual void Render( IRenderContext *pRenderContext, PlatWindow_t hWnd, const Rect_t &viewport, DmeTime_t flCurrentTime );
virtual void UseGameInputSystemEventQueue( bool bEnable );
virtual void RegisterInputEvent( const InputEvent_t &iEvent );
virtual void SendEventToAllScreens( KeyValues *kvGlobalEvent );
virtual void PostEventToAllScreens( KeyValues *kvGlobalEvent );
virtual void SetSoundPlayback( IGameUISoundPlayback *pPlayback );
virtual bool IsMenuVisible() const;
virtual void SetInputContext( InputContextHandle_t hInputContext );
CHitArea *GetMouseFocus();
CHitArea *GetMouseFocus( int x, int y );
CHitArea *GetKeyFocus();
CHitArea *GetRequestedKeyFocus();
void RequestKeyFocus( CHitArea *pGraphic, KeyValues *args = NULL );
void GetScreenHeightForFontLoading( int &nTall );
void SetScheme( IGameUIScheme * scheme );
IGameUIScheme * GetCurrentScheme();
DmeTime_t GetTime();
// Render system stuff
RenderInputLayout_t m_hInputLayout;
RenderShaderHandle_t m_hVertexShader;
RenderShaderHandle_t m_hPixelShader;
ConstantBufferHandle_t m_hConstBuffer;
void OnMouseFocusGained( CHitArea *mouseFocus );
void OnMouseFocusLost( CHitArea *mouseFocus );
bool OnKeyCodeTyped( const ButtonCode_t &code );
bool OnKeyTyped( const wchar_t &unichar );
bool OnGameGraphicScriptEvent( CGameGraphic *pGraphic, KeyValues *kvEvent );
// Force focus to update on the next frame
void ForceFocusUpdate(){ m_bForceFocusUpdate = true; }
void PlayMenuSound( const char *pSoundFileName );
void StopMenuSound( const char *pSoundFileName );
void SetWindowSize( int nWidth, int nHeight );
void GetWindowSize( int &nWidth, int &nHeight );
void SetViewportSize( int nWidth, int nHeight );
void GetViewportSize( int &nWidth, int &nHeight );
// Returns the input context to use to control the cursor
InputContextHandle_t GetInputContext( ) const;
void OnScreenReleased( CGameUISystem *pScreen );
// Dynamic texture management.
void InitImageAlias( const char *pAlias );
void LoadImageAliasTexture( const char *pAlias, const char *pBaseTextureName );
void ReleaseImageAlias( const char *pAlias);
IMaterial *GetImageAliasMaterial( const char *pAlias );
ImageAliasData_t *GetImageAliasData( const char *pAlias );
void TexCoordsToSheetTexCoords( const char *pAlias, Vector2D texCoords, Vector2D &sheetTexCoords );
void DrawDynamicTexture( const char *pAlias, int x, int y );
void ShowCursorCoords();
void ShowGraphicName();
virtual void RegisterGraphicClassFactory( char const *szGraphicClassName, IGameUIGraphicClassFactory *pFactory );
virtual IGameUIGraphicClassFactory *GetGraphicClassFactory( char const *szGraphicClassName );
virtual void InitRenderTargets();
virtual IMaterialProxy *CreateProxy( const char *proxyName );
private:
void GetScreenSize( int &nWide, int &nTall );
Vector2D CursorToStage( Vector2D cursorPos );
// We may wind up with multiple viewports and multiple lists?
Rect_t m_Viewport;
int m_nWindowWidth, m_nWindowHeight;
CUtlVector< CGameUISystem * > m_ActiveMenuList;
CUtlVector< CGameUISystem * > m_ReleasedMenuList;
DmeTime_t m_flCurrentTime;
IGameUIScheme *m_Scheme;
CHitArea *m_RequestedKeyFocus;
bool m_bForceFocusUpdate;
bool m_bUseGameInputQueue;
InputContextHandle_t m_hInputContext;
IGameUISoundPlayback *m_pSoundPlayback;
CUtlVector< InputEvent_t > m_InputQueue;
CUtlVector< KeyValues * > m_GameUIEventMainQueue;
CUtlVector< CUtlString > m_MenuFileNames;
CUtlMap< CUtlString, void * > m_MenuSoundMap;
typedef CUtlMap< CUtlString, IGameUIScreenControllerFactory * > ScreenControllerFactoryMap;
ScreenControllerFactoryMap m_ScreenControllerMap;
typedef CUtlMap< CUtlString, IGameUIGraphicClassFactory * > GameUIGraphicClassFactoryMap;
GameUIGraphicClassFactoryMap m_GraphicClassMap;
bool m_bVisible;
bool m_bSetReleaseTimer;
DmeTime_t m_ReleaseStartTime;
DmeTime_t m_ReleaseTime;
CGameText *m_pCursorText;
};
extern CGameUISystemMgr *g_pGameUISystemMgrImpl;
bool UtlStringLessFunc( const CUtlString &lhs, const CUtlString &rhs );
#endif // GAMEUISYSTEMMANAGER_H

View File

@@ -0,0 +1,763 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#define SUPPORT_CUSTOM_FONT_FORMAT
#ifdef SUPPORT_CUSTOM_FONT_FORMAT
#define _WIN32_WINNT 0x0500
#endif
#include "gameuisystemsurface.h"
#include "gameuisystemmgr.h"
#include "vgui_surfacelib/fontmanager.h"
#include "vgui_surfacelib/texturedictionary.h"
#include "vgui_surfacelib/fonttexturecache.h"
#include "vgui/isystem.h"
#include "tier1/utlbuffer.h"
#include "tier1/keyvalues.h"
#include "materialsystem/imesh.h"
#include "gameuischeme.h"
#include "vgui_controls/Controls.h"
#include "rendersystem/irendercontext.h"
#include "rendersystem/vertexdata.h"
#include "rendersystem/indexdata.h"
#include "GameLayer.h"
#if defined( _X360 )
#include "xbox/xbox_win32stubs.h"
#endif
#include "xbox/xboxstubs.h"
#include "valvefont.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Helper function for getting the language the game ui should use.
//-----------------------------------------------------------------------------
static void HelperGetLanguage( char *pLanguageBuf, int bufSize )
{
bool bValid = false;
if ( IsPC() )
{
bValid = vgui::system()->GetRegistryString( "HKEY_CURRENT_USER\\Software\\Valve\\Steam\\Language", pLanguageBuf, bufSize - 1 );
}
else
{
Q_strncpy( pLanguageBuf, XBX_GetLanguageString(), bufSize );
bValid = true;
}
if ( !bValid )
{
Q_strncpy( pLanguageBuf, "english", bufSize );
}
}
//-----------------------------------------------------------------------------
// Globals...
//-----------------------------------------------------------------------------
static CFontTextureCache g_FontTextureCache;
//-----------------------------------------------------------------------------
// Singleton instance
//-----------------------------------------------------------------------------
CGameUISystemSurface g_GameUISystemSurface;
CGameUISystemSurface *g_pGameUISystemSurface = &g_GameUISystemSurface;
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameUISystemSurface::CGameUISystemSurface()
{
m_bIsInitialized = false;
g_FontTextureCache.SetPrefix( "ingameui" );
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGameUISystemSurface::~CGameUISystemSurface()
{
m_CustomFontFileNames.RemoveAll();
m_BitmapFontFileNames.RemoveAll();
m_BitmapFontFileMapping.RemoveAll();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
InitReturnVal_t CGameUISystemSurface::Init()
{
if ( m_bIsInitialized )
return INIT_OK;
// fonts initialization
char language[64];
HelperGetLanguage( language, 64 );
FontManager().SetLanguage( language );
m_bIsInitialized = true;
return INIT_OK;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUISystemSurface::Shutdown( void )
{
// Release all textures
TextureDictionary()->DestroyAllTextures();
#if !defined( _GAMECONSOLE )
HMODULE gdiModule = NULL;
#ifdef SUPPORT_CUSTOM_FONT_FORMAT
; // on custom font format Windows takes care of cleaning up the font when the process quits
#else
// release any custom font files
// use newer function if possible
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 // SUPPORT_CUSTOM_FONT_FORMAT
#endif
m_CustomFontFileNames.RemoveAll();
m_BitmapFontFileNames.RemoveAll();
m_BitmapFontFileMapping.RemoveAll();
#if !defined( _GAMECONSOLE )
if ( gdiModule )
{
::FreeLibrary(gdiModule);
}
#endif
}
//-----------------------------------------------------------------------------
// Purpose: adds a custom font file (supports valve .vfont files)
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::AddCustomFontFile( const char *fontFileName )
{
if ( IsGameConsole() )
{
// custom fonts are not supported (not needed) on xbox, all .vfonts are offline converted to ttfs
// ttfs are mounted/handled elsewhere
return true;
}
char fullPath[MAX_PATH];
bool bFound = false;
// windows needs an absolute path for ttf
bFound = g_pFullFileSystem->GetLocalPath( fontFileName, fullPath, sizeof( fullPath ) ) ? true : false;
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() )
{
#ifdef SUPPORT_CUSTOM_FONT_FORMAT
// We don't need the actual file on disk
#else
// 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 );
#endif
}
}
#if !defined( _GAMECONSOLE )
#ifdef SUPPORT_CUSTOM_FONT_FORMAT
// 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 false;
}
if ( !ValveFont::DecodeFont( buf ) )
{
Msg( "Failed to parse custom font file '%s'\n", fontFileName );
return false;
}
DWORD dwNumFontsRegistered = 0;
HANDLE hRegistered = NULL;
hRegistered = ::AddFontMemResourceEx( buf.Base(), buf.TellPut(), NULL, &dwNumFontsRegistered );
if ( !hRegistered )
{
Msg( "Failed to register custom font file '%s'\n", fontFileName );
return false;
}
return hRegistered != NULL;
#else
// 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
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;
#endif // SUPPORT_CUSTOM_FONT_FORMAT
#else
return true;
#endif
}
//-----------------------------------------------------------------------------
// Purpose: adds a bitmap font file
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::AddBitmapFontFile( const char *fontFileName )
{
bool bFound = false;
bFound = ( ( g_pFullFileSystem->GetDVDMode() == DVDMODE_STRICT ) || g_pFullFileSystem->FileExists( fontFileName, IsGameConsole() ? "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 CGameUISystemSurface::SetBitmapFontName( const char *pName, const char *pFontFilename )
{
char fontPath[MAX_PATH];
Q_strncpy( fontPath, pFontFilename, MAX_PATH );
Q_strlower( fontPath );
CUtlSymbol sym( fontPath );
for ( int 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 *CGameUISystemSurface::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();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUISystemSurface::ClearTemporaryFontCache( void )
{
FontManager().ClearTemporaryFontCache();
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CGameUISystemSurface::GetFontName( FontHandle_t font )
{
return FontManager().GetFontName( font );
}
//-----------------------------------------------------------------------------
// Causes fonts to get reloaded, etc.
//-----------------------------------------------------------------------------
void CGameUISystemSurface::ResetFontCaches()
{
// Don't do this on x360!!!
if ( IsGameConsole() )
return;
// clear font texture cache
g_FontTextureCache.Clear();
g_pGameUISchemeManager->ReloadFonts();
}
//-----------------------------------------------------------------------------
// Purpose: cap bits
// Warning: if you change this, make sure the SurfaceV28 wrapper above reports
// the correct capabilities.
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::SupportsFontFeature( FontFeature_t feature )
{
switch ( feature )
{
case FONT_FEATURE_ANTIALIASED_FONTS:
case FONT_FEATURE_DROPSHADOW_FONTS:
return true;
case FONT_FEATURE_OUTLINE_FONTS:
if ( IsGameConsole() )
return false;
return true;
default:
return false;
};
}
//-----------------------------------------------------------------------------
// Purpose: Force a set of characters to be rendered into the font page.
//-----------------------------------------------------------------------------
void CGameUISystemSurface::PrecacheFontCharacters( FontHandle_t font, wchar_t *pCharacterString )
{
wchar_t *pCommonChars = L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789,.!:-/%";
if ( !pCharacterString || !pCharacterString[0] )
{
// use the common chars, alternate languages are not handled
pCharacterString = pCommonChars;
}
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( font, FONT_DRAW_DEFAULT, pCharacterString, pTextureIDs_ignored, pTexCoords_ignored, numChars );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUISystemSurface::DrawFontTexture( int textureId, int xPos, int yPos )
{
Assert( g_pMaterialSystem );
IMaterial *pMaterial = GetMaterial( textureId );
if (!pMaterial)
{
return;
}
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
if ( !pMesh )
return;
unsigned char textColor[4];
textColor[0] = 255;
textColor[1] = 255;
textColor[2] = 255;
textColor[3] = 255;
int x = xPos;
int y = yPos;
int wide;
int tall;
TextureDictionary()->GetTextureSize( textureId, wide, tall );
CMeshBuilder meshBuilder;
meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
meshBuilder.Position3f( x, y, 0 );
meshBuilder.Color4ubv( textColor );
meshBuilder.TexCoord2f( 0, 0, 0 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( x + wide, y, 0 );
meshBuilder.Color4ubv( textColor );
meshBuilder.TexCoord2f( 0, 1, 0 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( x + wide, y + tall, 0 );
meshBuilder.Color4ubv( textColor );
meshBuilder.TexCoord2f( 0, 1, 1 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.Position3f( x, y + tall, 0 );
meshBuilder.Color4ubv( textColor );
meshBuilder.TexCoord2f( 0, 0, 1 );
meshBuilder.AdvanceVertexF<VTX_HAVEPOS | VTX_HAVECOLOR, 1>();
meshBuilder.End();
pMesh->Draw();
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CGameUISystemSurface::DrawFontTexture( IRenderContext *pRenderContext, int textureId, int xPos, int yPos )
{
HRenderTexture fontTextureHandle = g_pGameUISystemSurface->GetTextureHandle( textureId );
pRenderContext->BindTexture( 0, fontTextureHandle );
VertexColor_t textColor( 255, 255, 255, 255);
int x = xPos;
int y = yPos;
int wide;
int tall;
TextureDictionary()->GetTextureSize( textureId, wide, tall );
CDynamicVertexData< GameUIVertex_t > vb( pRenderContext, 4, "gamelayer2", "game_controls2" );
vb.Lock();
vb->m_vecPosition.Init( x, y, 0.0f );
vb->m_color = textColor;
vb->m_vecTexCoord.Init( 0, 0 );
vb.AdvanceVertex();
vb->m_vecPosition.Init( x + wide, y, 0.0f );
vb->m_color = textColor;
vb->m_vecTexCoord.Init( 1, 0 );
vb.AdvanceVertex();
vb->m_vecPosition.Init( x+ wide, y + tall, 0.0f );
vb->m_color = textColor;
vb->m_vecTexCoord.Init( 1, 1 );
vb.AdvanceVertex();
vb->m_vecPosition.Init( x, y + tall, 0.0f );
vb->m_color = textColor;
vb->m_vecTexCoord.Init( 0, 1 );
vb.AdvanceVertex();
vb.Unlock();
vb.Bind( 0, 0 );
CDynamicIndexData< uint16 > ib( pRenderContext, 6, "gamelayer", "game_controls" );
ib.Lock();
ib.Index( 0 );
ib.Index( 1 );
ib.Index( 2 );
ib.Index( 0);
ib.Index( 2 );
ib.Index( 3 );
ib.Unlock();
ib.Bind( 0 );
pRenderContext->DrawIndexed( RENDER_PRIM_TRIANGLES, 0, 6 );
}
//-----------------------------------------------------------------------------
// Purpose: Gets the material and texture coords for this char.
// Set up info.drawtype and set the font first.
//-----------------------------------------------------------------------------
IMaterial *CGameUISystemSurface::GetTextureForChar( FontCharRenderInfo &info, float **texCoords )
{
bool bSuccess = g_FontTextureCache.GetTextureForChar( info.currentFont, info.drawType, info.ch, &info.textureId, texCoords );
if ( !bSuccess )
{
return NULL;
}
return TextureDictionary()->GetTextureMaterial( info.textureId );
}
//-----------------------------------------------------------------------------
// Purpose: Gets the material and texture coords for this char.
// Set up info.drawtype and set the font first.
// This call doesnt use the static in the font cache to store the texcoords.
//-----------------------------------------------------------------------------
IMaterial *CGameUISystemSurface::GetTextureAndCoordsForChar( FontCharRenderInfo &info, float *texCoords )
{
bool bSuccess = g_FontTextureCache.GetTextureAndCoordsForChar( info.currentFont, info.drawType, info.ch, &info.textureId, texCoords );
if ( !bSuccess )
{
return NULL;
}
return TextureDictionary()->GetTextureMaterial( info.textureId );
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::GetUnicodeCharRenderPositions( FontCharRenderInfo& info, Vector2D *pPositions )
{
info.valid = false;
if ( !info.currentFont )
{
return info.valid;
}
info.valid = true;
info.fontTall = GetFontTall( info.currentFont );
GetCharABCwide( info.currentFont, info.ch, info.abcA, info.abcB, info.abcC );
bool bUnderlined = FontManager().GetFontUnderlined( info.currentFont );
// 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( info.currentFont, info.drawType, info.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;
}
pPositions[0].x = info.x;
pPositions[0].y = info.y;
pPositions[1].x = info.x + fontWide;
pPositions[1].y = info.y;
pPositions[2].x = info.x + fontWide;
pPositions[2].y = info.y + info.fontTall;
pPositions[3].x = info.x;
pPositions[3].y = info.y + info.fontTall;
return info.valid;
}
//-----------------------------------------------------------------------------
// Purpose: adds glyphs to a font created by CreateFont()
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::SetBitmapFontGlyphSet( FontHandle_t font, const char *windowsFontName, float scalex, float scaley, int flags)
{
return FontManager().SetBitmapFontGlyphSet( font, windowsFontName, scalex, scaley, flags );
}
//-----------------------------------------------------------------------------
// Purpose: creates a new empty font
//-----------------------------------------------------------------------------
FontHandle_t CGameUISystemSurface::CreateFont()
{
return FontManager().CreateFont();
}
//-----------------------------------------------------------------------------
// Purpose: adds glyphs to a font created by CreateFont()
//-----------------------------------------------------------------------------
bool CGameUISystemSurface::SetFontGlyphSet( FontHandle_t 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: returns the max height of a font
//-----------------------------------------------------------------------------
int CGameUISystemSurface::GetFontTall( FontHandle_t font )
{
return FontManager().GetFontTall( font );
}
//-----------------------------------------------------------------------------
// Purpose: returns the abc widths of a single character
// This is used by text classes to handle kerning.
//-----------------------------------------------------------------------------
void CGameUISystemSurface::GetCharABCwide( FontHandle_t 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 CGameUISystemSurface::GetCharacterWidth( FontHandle_t font, int ch )
{
return FontManager().GetCharacterWidth( font, ch );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial *CGameUISystemSurface::GetMaterial( int textureId )
{
return TextureDictionary()->GetTextureMaterial( textureId );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
HRenderTexture CGameUISystemSurface::GetTextureHandle( int textureId )
{
return TextureDictionary()->GetTextureHandle( textureId );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGameUISystemSurface::SetLanguage( const char *pLanguage )
{
FontManager().SetLanguage( pLanguage );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
const char *CGameUISystemSurface::GetLanguage()
{
return FontManager().GetLanguage();
}

View File

@@ -0,0 +1,100 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEUISYSTEMSURFACE_H
#define GAMEUISYSTEMSURFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "igameuisystemmgr.h"
#include "materialsystem/imaterialsystem.h"
#include "vgui_surfacelib/ifontsurface.h"
#include "tier1/utldict.h"
#include "rendersystem/irenderdevice.h"
class CFontTextureCache;
class KeyValues;
//-----------------------------------------------------------------------------
// This class is the interface to the font and font texture, systems.
// Load fonts given by schemes into the systems using this class.
//-----------------------------------------------------------------------------
class CGameUISystemSurface : public IGameUISystemSurface
{
public:
CGameUISystemSurface();
~CGameUISystemSurface();
InitReturnVal_t Init();
void Shutdown();
void PrecacheFontCharacters( FontHandle_t font, wchar_t *pCharacterString = NULL );
FontHandle_t CreateFont();
bool SetFontGlyphSet( FontHandle_t font, const char *windowsFontName, int tall, int weight, int blur, int scanlines, int flags, int nRangeMin = 0, int nRangeMax = 0 );
int GetFontTall( FontHandle_t font );
void GetCharABCwide( FontHandle_t font, int ch, int &a, int &b, int &c );
int GetCharacterWidth( FontHandle_t font, int ch );
const char *GetFontName( FontHandle_t font );
bool AddCustomFontFile( const char *fontFileName );
// Helper fxns for loading bitmap fonts
bool AddBitmapFontFile( const char *fontFileName );
void SetBitmapFontName( const char *pName, const char *pFontFilename );
const char *GetBitmapFontName( const char *pName );
bool SetBitmapFontGlyphSet( FontHandle_t font, const char *windowsFontName, float scalex, float scaley, int flags);
void ClearTemporaryFontCache( void );
// Causes fonts to get reloaded, etc.
void ResetFontCaches();
bool SupportsFontFeature( FontFeature_t feature );
void DrawSetTextureRGBA( int id, const unsigned char* rgba, int wide, int tall ){}
void DrawSetTextureRGBAEx( int id, const unsigned char* rgba, int wide, int tall, ImageFormat format ){}
bool GetUnicodeCharRenderPositions( FontCharRenderInfo& info, Vector2D *pPositions );
IMaterial *GetTextureForChar( FontCharRenderInfo &info, float **texCoords );
IMaterial *GetTextureAndCoordsForChar( FontCharRenderInfo &info, float *texCoords );
// Used for debugging.
void DrawFontTexture( int textureId, int xPos, int yPos );
void DrawFontTexture( IRenderContext *pRenderContext, int textureId, int xPos, int yPos );
IMaterial *GetMaterial( int textureId );
HRenderTexture GetTextureHandle( int textureId );
void GetProportionalBase( int &width, int &height ) { width = BASE_WIDTH; height = BASE_HEIGHT; }
void SetLanguage( const char *pLanguage );
const char *GetLanguage();
private:
enum { BASE_HEIGHT = 480, BASE_WIDTH = 640 };
bool m_bIsInitialized;
CUtlVector< CUtlSymbol > m_CustomFontFileNames;
CUtlVector< CUtlSymbol > m_BitmapFontFileNames;
CUtlDict< int, int > m_BitmapFontFileMapping;
};
extern CGameUISystemSurface *g_pGameUISystemSurface;
#endif // GAMEUISYSTEMSURFACE_H

View File

@@ -0,0 +1,396 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "graphicgroup.h"
#include "gamegraphic.h"
#include "gameuidefinition.h"
#include "animdata.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
BEGIN_DMXELEMENT_UNPACK ( CGraphicGroup )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
DMXELEMENT_UNPACK_FIELD( "center", "0 0", Vector2D, m_Geometry.m_Center )
DMXELEMENT_UNPACK_FIELD( "scale", "1 1", Vector2D, m_Geometry.m_Scale )
DMXELEMENT_UNPACK_FIELD( "rotation", "0", float, m_Geometry.m_Rotation )
DMXELEMENT_UNPACK_FIELD( "maintainaspectratio", "0", bool, m_Geometry.m_bMaintainAspectRatio )
DMXELEMENT_UNPACK_FIELD( "sublayertype", "0", int, m_Geometry.m_Sublayer )
DMXELEMENT_UNPACK_FIELD( "visible", "1", bool, m_Geometry.m_bVisible )
DMXELEMENT_UNPACK_FIELD( "initialstate", "-1", int, m_CurrentState )
DMXELEMENT_UNPACK_FIELD( "horizgradient", "0", bool, m_Geometry.m_bHorizontalGradient )
DMXELEMENT_UNPACK_FIELD( "color", "255 255 255 255", Color, m_Geometry.m_Color )
DMXELEMENT_UNPACK_FIELD( "topcolor", "255 255 255 255", Color, m_Geometry.m_TopColor )
DMXELEMENT_UNPACK_FIELD( "bottomcolor", "255 255 255 255", Color, m_Geometry.m_BottomColor )
END_DMXELEMENT_UNPACK( CGraphicGroup, s_GraphicGroupUnpack )
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGraphicGroup::CGraphicGroup()
{
m_ResultantColor.r = 0;
m_ResultantColor.g = 0;
m_ResultantColor.b = 0;
m_ResultantColor.a = 0;
}
CGraphicGroup::~CGraphicGroup()
{
}
//-----------------------------------------------------------------------------
// Load data from file.
//-----------------------------------------------------------------------------
bool CGraphicGroup::Unserialize( CDmxElement *pElement, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping )
{
pElement->UnpackIntoStructure( this, s_GraphicGroupUnpack );
CDmxAttribute *pGroupElements = pElement->GetAttribute( "groupElements" );
if ( !pGroupElements || pGroupElements->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &elements = pGroupElements->GetArray< CDmxElement * >( );
int nCount = elements.Count();
for ( int i = 0; i < nCount; ++i )
{
// Find the element in the map.
char pBuf[255];
UniqueIdToString( elements[i]->GetId(), pBuf, 255 );
int index = unserializedGraphicMapping.Find( pBuf );
Assert( unserializedGraphicMapping.IsValidIndex( index ) );
CGameGraphic *pGraphic = unserializedGraphicMapping.Element(index);
pGraphic->SetGroup( this );
m_MemberList.AddToTail( pGraphic );
}
// ANIMSTATES
CDmxAttribute *pImageAnims = pElement->GetAttribute( "imageanims" );
if ( !pImageAnims || pImageAnims->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &imageanims = pImageAnims->GetArray< CDmxElement * >( );
nCount = imageanims.Count();
for ( int i = 0; i < nCount; ++i )
{
CAnimData *pAnimData = new CAnimData;
if ( !pAnimData->Unserialize( imageanims[i] ) )
{
delete pAnimData;
return false;
}
m_Anims.AddToTail( pAnimData );
}
char pBuf[255];
UniqueIdToString( pElement->GetId(), pBuf, 255 );
unserializedGraphicMapping.Insert( pBuf, this );
// Ok the initial state is 0, which is (usually ) default.
// default could be aliased to another state though so if it is fix the initial state here.
// default might also not be the state that is 0 so this sets the graphic's initial
// state to be the default one.
SetState( "default" );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGraphicGroup::UpdateGeometry()
{
if ( m_CurrentState == -1 )
return;
DmeTime_t flAnimTime = GetAnimationTimePassed();
// Update color
m_Anims[ m_CurrentState ]->m_ColorAnim.GetValue( flAnimTime, &m_Geometry.m_Color );
// Update center location
m_Anims[ m_CurrentState ]->m_CenterPosAnim.GetValue( flAnimTime, &m_Geometry.m_Center );
// Update scale
m_Anims[ m_CurrentState ]->m_ScaleAnim.GetValue( flAnimTime, &m_Geometry.m_Scale );
// Update rotation
m_Anims[ m_CurrentState ]->m_RotationAnim.GetValue( flAnimTime, &m_Geometry.m_Rotation );
for ( int i = 0; i < m_MemberList.Count(); ++i )
{
m_MemberList[i]->UpdateGeometry();
}
}
//-----------------------------------------------------------------------------
// Store the resultant color for groups so kids can just get that.
//-----------------------------------------------------------------------------
void CGraphicGroup::UpdateRenderData( color32 parentColor )
{
if ( !m_Geometry.m_bVisible )
return;
m_ResultantColor.r = (int)( (float)m_Geometry.m_Color.r * (float)(parentColor.r/255.0) );
m_ResultantColor.g = (int)( (float)m_Geometry.m_Color.g * (float)(parentColor.g/255.0) );
m_ResultantColor.b = (int)( (float)m_Geometry.m_Color.b * (float)(parentColor.b/255.0) );
m_ResultantColor.a = (int)( (float)m_Geometry.m_Color.a * (float)(parentColor.a/255.0) );
// Update any children that are groups
// Graphic members are not done because the colors are calculated when we get the render data out.
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
if ( m_MemberList[i]->IsGroup() )
{
CGraphicGroup *pGroup = (CGraphicGroup *)m_MemberList[i];
pGroup->UpdateRenderData( parentColor );
}
}
}
//-----------------------------------------------------------------------------
// Populate lists for rendering
//-----------------------------------------------------------------------------
void CGraphicGroup::UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo )
{
m_Geometry.UpdateRenderTransforms( stageRenderInfo, GetGroup() );
// Create a matrix that ensures no aspect ratio changes.
// Update positions relative to the center, texture coords, and vertex colors
// If the group maintains aspect ratio it will already have handled this in its transform update.
Vector2D center;
// If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
matrix3x4_t screenScalemat;
SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat );
Vector centerVec( m_Geometry.m_Center.x, m_Geometry.m_Center.y, 0 );
Vector centerInScreen;
VectorTransform( centerVec, screenScalemat, centerInScreen );
center.x = centerInScreen.x;
center.y = centerInScreen.y;
matrix3x4_t transmat;
Vector position( center.x, center.y, 0 );
SetIdentityMatrix( transmat );
PositionMatrix( position, transmat );
matrix3x4_t scalemat;
SetScaleMatrix( m_Geometry.m_Scale.x, m_Geometry.m_Scale.y, 1, scalemat );
matrix3x4_t rotmat;
Vector axis( 0, 0, 1 );
MatrixBuildRotationAboutAxis( axis, m_Geometry.m_Rotation, rotmat );
matrix3x4_t temp;
MatrixMultiply( rotmat, scalemat, temp );
matrix3x4_t rawToLocal;
MatrixMultiply( transmat, temp, rawToLocal );
matrix3x4_t groupToScreen;
// Use the matrix that doesn't contain any scale changes if we should
m_pGroup->GetRenderTransform( groupToScreen, true );
MatrixMultiply( groupToScreen, rawToLocal, m_RelToScreenHoldAspectRatio );
// Update all children
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->UpdateRenderTransforms( stageRenderInfo );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGraphicGroup::AddToGroup( CGameGraphic *pGraphic )
{
m_MemberList.AddToTail( pGraphic );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGraphicGroup::RemoveFromGroup( CGameGraphic *pGraphic )
{
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
// TODO, what if the graphic is a group?
if ( m_MemberList[i] == pGraphic )
{
m_MemberList.Remove( i );
return;
}
}
}
//-----------------------------------------------------------------------------
// Returns true if any graphic in this group has the state.
//-----------------------------------------------------------------------------
bool CGraphicGroup::HasState( const char *pStateName )
{
if ( CGameGraphic::HasState( pStateName ) )
return true;
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
if ( m_MemberList[i]->HasState( pStateName ) )
return true;
}
return false;
}
//-----------------------------------------------------------------------------
// Set the state of all members to this state
//-----------------------------------------------------------------------------
void CGraphicGroup::SetState( const char *pStateName )
{
CGameGraphic::SetState( pStateName );
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->SetState( pStateName );
}
}
//-----------------------------------------------------------------------------
// Start playing animations
//-----------------------------------------------------------------------------
void CGraphicGroup::StartPlaying()
{
CGameGraphic::StartPlaying();
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->StartPlaying();
}
}
//-----------------------------------------------------------------------------
// Stop playing animations
//-----------------------------------------------------------------------------
void CGraphicGroup::StopPlaying()
{
CGameGraphic::StopPlaying();
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->StopPlaying();
}
}
//-----------------------------------------------------------------------------
// Move all members to the next available state
// Note this could put all of them into different states
//-----------------------------------------------------------------------------
void CGraphicGroup::AdvanceState()
{
CGameGraphic::AdvanceState();
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
m_MemberList[i]->AdvanceState();
}
}
//-----------------------------------------------------------------------------
// Return the first member of this group that can have keyfocus.
//-----------------------------------------------------------------------------
CHitArea *CGraphicGroup::GetKeyFocusRequestGraphic()
{
for ( int i = 0; i < m_MemberList.Count(); i++ )
{
if ( m_MemberList[i]->CanAcceptInput() )
{
return ( CHitArea * )m_MemberList[i];
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Does this graphic own a graphic with this name?
//-----------------------------------------------------------------------------
CGameGraphic *CGraphicGroup::FindGraphicByName( const char *pName ) const
{
int nGraphicCount = m_MemberList.Count();
for ( int i = 0; i < nGraphicCount; ++i )
{
CGameGraphic *pMember = m_MemberList[i];
if ( pMember->IsGraphicNamed( pName ) )
{
// Match.
return pMember;
}
}
return NULL;
}
//-----------------------------------------------------------------------------
// Group visibility affects all children.
//-----------------------------------------------------------------------------
void CGraphicGroup::SetVisible( bool bVisible )
{
CGameGraphic::SetVisible( bVisible );
int nGraphicCount = m_MemberList.Count();
for ( int i = 0; i < nGraphicCount; ++i )
{
CGameGraphic *pMember = m_MemberList[i];
pMember->SetVisible( bVisible );
}
}
//-----------------------------------------------------------------------------
// Return the appropriate render transform.
// m_RelToScreenHoldAspectRatio is calculated for a stage aspect ratio that has not changed.
//-----------------------------------------------------------------------------
void CGraphicGroup::GetRenderTransform( matrix3x4_t &relToScreen, bool bMaintainAspectRatio ) const
{
if ( bMaintainAspectRatio )
{
relToScreen = m_RelToScreenHoldAspectRatio;
}
else
{
relToScreen = m_Geometry.m_RenderToScreen;
}
}
//-----------------------------------------------------------------------------
// If any parent of this group should maintain aspect ratio, this group should.
//-----------------------------------------------------------------------------
bool CGraphicGroup::MaintainAspectRatio() const
{
if ( m_pGroup && !m_Geometry.m_bMaintainAspectRatio )
{
return m_pGroup->MaintainAspectRatio();
}
return m_Geometry.m_bMaintainAspectRatio;
}

View File

@@ -0,0 +1,79 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GRAPHICGROUP_H
#define GRAPHICGROUP_H
#ifdef _WIN32
#pragma once
#endif
#include "dmxloader/dmxelement.h"
#include "tier1/utlvector.h"
#include "tier1/utldict.h"
#include "gamegraphic.h"
#include "hitarea.h"
//-----------------------------------------------------------------------------
// A class that holds a group of graphics.
//-----------------------------------------------------------------------------
class CGraphicGroup : public CGameGraphic
{
DECLARE_DMXELEMENT_UNPACK()
public:
CGraphicGroup();
virtual ~CGraphicGroup();
bool Unserialize( CDmxElement *pElement, CUtlDict< CGameGraphic *, int > &unserializedGraphicMapping );
virtual void UpdateGeometry();
void UpdateRenderData( color32 parentColor );
virtual void UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo );
color32 GetResultantColor() const { return m_ResultantColor; } // needed by group children.
virtual void GetRenderTransform( matrix3x4_t &relToScreen, bool bMaintainAspectRatio ) const; // needed by group children.
void AddToGroup( CGameGraphic *pGraphic );
void RemoveFromGroup( CGameGraphic *pGraphic );
// From GameGraphic
virtual bool HasState( const char *pStateName );
virtual void SetState( const char *pStateName );
virtual void StartPlaying();
virtual void StopPlaying();
virtual void AdvanceState();
virtual bool IsGroup() const { return true; }
virtual bool IsStageGroup()const { return false; }
CHitArea *GetKeyFocusRequestGraphic();
virtual CGameGraphic *FindGraphicByName( const char *pName ) const;
virtual void SetVisible( bool bVisible );
bool MaintainAspectRatio() const;
protected:
CUtlVector< CGameGraphic * > m_MemberList;
color32 m_ResultantColor;
private:
matrix3x4_t m_RelToScreenHoldAspectRatio;
};
#endif // GRAPHICGROUP_H

View File

@@ -0,0 +1,55 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "graphicscriptinterface.h"
#include "gamegraphic.h"
#include "gameuisystemmgr.h"
BEGIN_SCRIPTDESC_ROOT_NAMED( CGraphicScriptInterface, "CGraphicScriptInterface", SCRIPT_SINGLETON "" )
DEFINE_SCRIPTFUNC( PlayAnim, "Play an animation by name" )
END_SCRIPTDESC()
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CGraphicScriptInterface::CGraphicScriptInterface( IScriptVM *pScriptVM )
{
m_pScriptVM = pScriptVM;
m_pGraphic = NULL;
HSCRIPT Scope = m_pScriptVM->RegisterInstance( this, "Graphic" );
SetScope( Scope );
}
//-----------------------------------------------------------------------------
// Tell this script what graphic it belongs to.
//-----------------------------------------------------------------------------
void CGraphicScriptInterface::InstallGraphic( CGameGraphic *pGraphic )
{
m_pGraphic = pGraphic;
}
//-----------------------------------------------------------------------------
// Play an animation on the graphic.
//-----------------------------------------------------------------------------
void CGraphicScriptInterface::PlayAnim( const char *pAnimName )
{
Assert( m_pGraphic );
if ( !m_pGraphic->HasState( pAnimName ) )
{
Warning( "Unable to find state %s for graphic %s\n", pAnimName, m_pGraphic->GetName() );
return;
}
m_pGraphic->SetState( pAnimName );
}

View File

@@ -0,0 +1,47 @@
//===== Copyright <20> Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
//===========================================================================//
#ifndef GRAPHICSCRIPTINTERFACE_H
#define GRAPHICSCRIPTINTERFACE_H
#ifdef _WIN32
#pragma once
#endif
#include "gameuiscriptsystem.h"
class CGameGraphic;
//-----------------------------------------------------------------------------
// These are functions that can be called from lua that do things to graphic classes.
//-----------------------------------------------------------------------------
class CGraphicScriptInterface
{
public:
CGraphicScriptInterface( IScriptVM *pScriptVM );
void InstallGraphic( CGameGraphic *pGraphic );
HSCRIPT GetScope( ) { return m_Scope; }
private:
// private functions to support scripting
//CGameGraphic *FindGraphic( int nID );
public:
// exposed functions to scripting
void PlayAnim( const char *pAnimName );
private:
void SetScope( HSCRIPT Scope ) { m_Scope = Scope; }
CGameGraphic *m_pGraphic;
HSCRIPT m_Scope;
IScriptVM *m_pScriptVM;
};
#endif // GRAPHICSCRIPTINTERFACE_H

View File

@@ -0,0 +1,730 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "hitarea.h"
// To handle scaling
#include "materialsystem/imaterialsystem.h"
#include "animdata.h"
#include "inputsystem/inputenums.h"
#include "inputsystem/analogcode.h"
#include "inputsystem/buttoncode.h"
#include "gameuisystemmgr.h"
#include "graphicgroup.h"
#include "inputgameui.h"
#include "graphicscriptinterface.h"
#include "inputgameui.h"
#include "gameuisystemmgr.h"
#include "gameuiscript.h"
#include "gameuisystem.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
#define DEBUG_INPUT_EVENTS 0
// Class factory for scripting.
class CHitAreaClassFactory : IGameUIGraphicClassFactory
{
public:
CHitAreaClassFactory()
{
Assert( g_pGameUISystemMgrImpl );
g_pGameUISystemMgrImpl->RegisterGraphicClassFactory( "hitarea", this );
}
// Returns an instance of a graphic interface (keyvalues owned by caller)
virtual CGameGraphic *CreateNewGraphicClass( KeyValues *kvRequest, CGameUIDefinition *pMenu )
{
Assert( pMenu );
CHitArea *pNewGraphic = NULL;
const char *pName = kvRequest->GetString( "name", NULL );
if ( pName )
{
pNewGraphic = new CHitArea( pName );
// Rects are normally 0,0, doing this so we can see script created rects.
pNewGraphic->SetScale( 100, 100 );
pMenu->AddGraphicToLayer( pNewGraphic, SUBLAYER_STATIC );
// Now set the attributes.
for ( KeyValues *arg = kvRequest->GetFirstSubKey(); arg != NULL; arg = arg->GetNextKey() )
{
pNewGraphic->HandleScriptCommand( arg );
}
}
return pNewGraphic;
}
};
static CHitAreaClassFactory g_CDynamicRectClassFactory;
BEGIN_DMXELEMENT_UNPACK ( CHitArea )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "name", "", m_pName )
DMXELEMENT_UNPACK_FIELD( "center", "0 0", Vector2D, m_Geometry.m_Center )
DMXELEMENT_UNPACK_FIELD( "scale", "0 0", Vector2D, m_Geometry.m_Scale )
DMXELEMENT_UNPACK_FIELD( "rotation", "0", float, m_Geometry.m_Rotation )
DMXELEMENT_UNPACK_FIELD( "maintainaspectratio", "0", bool, m_Geometry.m_bMaintainAspectRatio )
DMXELEMENT_UNPACK_FIELD( "sublayertype", "0", int, m_Geometry.m_Sublayer )
DMXELEMENT_UNPACK_FIELD( "visible", "1", bool, m_Geometry.m_bVisible )
DMXELEMENT_UNPACK_FIELD( "initialstate", "-1", int, m_CurrentState )
DMXELEMENT_UNPACK_FIELD( "dragenabled", "0", bool, m_bDragEnabled )
DMXELEMENT_UNPACK_FIELD_UTLSTRING( "on_mouse_left_clicked_cmd", "", m_OnMouseLeftClickedScriptCommand )
END_DMXELEMENT_UNPACK( CHitArea, s_HitAreaUnpack )
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CHitArea::CHitArea( const char *pName )
{
m_bCanAcceptInput = true;
m_bCanStartDragging = false;
m_IsDragging = false;
m_DragStartCursorPos[0] = 0;
m_DragStartCursorPos[1] = 0;
m_DragCurrentCursorPos[0] = 0;
m_DragCurrentCursorPos[1] = 0;
// DME default values.
m_pName = pName;
m_Geometry.m_Center.x = 0;
m_Geometry.m_Center.y = 0;
m_Geometry.m_Scale.x = 0;
m_Geometry.m_Scale.y = 0;
m_Geometry.m_Rotation = 0;
m_Geometry.m_bMaintainAspectRatio = 0;
m_Geometry.m_Sublayer = 0;
m_Geometry.m_bVisible = true;
m_CurrentState = -1;
m_bDragEnabled = false;
m_OnMouseLeftClickedScriptCommand = NULL;
m_Geometry.m_RelativePositions.AddToTail( Vector2D( -.5, -.5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( .5, -.5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( .5, .5 ) );
m_Geometry.m_RelativePositions.AddToTail( Vector2D( -.5, .5 ) );
CTriangle triangle;
triangle.m_PointIndex[0] = 0;
triangle.m_PointIndex[1] = 1;
triangle.m_PointIndex[2] = 2;
m_Geometry.m_Triangles.AddToTail( triangle );
triangle.m_PointIndex[0] = 0;
triangle.m_PointIndex[1] = 2;
triangle.m_PointIndex[2] = 3;
m_Geometry.m_Triangles.AddToTail( triangle );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CHitArea::~CHitArea()
{
// TODO: move to manager?/ as it should control allocations and deallocations.
g_pInputGameUI->PanelDeleted( this );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CHitArea::Unserialize( CDmxElement *pGraphic )
{
pGraphic->UnpackIntoStructure( this, s_HitAreaUnpack );
// GEOMETRY
CDmxAttribute *pRelativePositions = pGraphic->GetAttribute( "relativepositions" );
if ( !pRelativePositions || pRelativePositions->GetType() != AT_VECTOR2_ARRAY )
{
return false;
}
const CUtlVector< Vector2D > &relpositions = pRelativePositions->GetArray< Vector2D >( );
int nCount = relpositions.Count();
m_Geometry.m_RelativePositions.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
m_Geometry.m_RelativePositions.AddToTail( Vector2D( relpositions[i].x, relpositions[i].y ) );
}
CDmxAttribute *pTriangles = pGraphic->GetAttribute( "triangles" );
if ( !pTriangles || pTriangles->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &triangles = pTriangles->GetArray< CDmxElement * >( );
nCount = triangles.Count();
m_Geometry.m_Triangles.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
CDmxAttribute *pPoints = triangles[i]->GetAttribute( "positionindexes" );
const CUtlVector< int > &points = pPoints->GetArray< int >( );
CTriangle triangle;
triangle.m_PointIndex[0] = points[0];
triangle.m_PointIndex[1] = points[1];
triangle.m_PointIndex[2] = points[2];
m_Geometry.m_Triangles.AddToTail( triangle );
}
// ANIMSTATES
CDmxAttribute *pImageAnims = pGraphic->GetAttribute( "imageanims" );
if ( !pImageAnims || pImageAnims->GetType() != AT_ELEMENT_ARRAY )
{
return false;
}
const CUtlVector< CDmxElement * > &imageanims = pImageAnims->GetArray< CDmxElement * >( );
nCount = imageanims.Count();
for ( int i = 0; i < nCount; ++i )
{
CAnimData *pAnimData = new CAnimData;
if ( !pAnimData->Unserialize( imageanims[i] ) )
{
delete pAnimData;
return false;
}
m_Anims.AddToTail( pAnimData );
}
SetState( "default" );
return true;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHitArea::UpdateGeometry()
{
if ( m_CurrentState == -1 )
return;
DmeTime_t flAnimTime = GetAnimationTimePassed();
// Update center location
m_Anims[ m_CurrentState ]->m_CenterPosAnim.GetValue( flAnimTime, &m_Geometry.m_Center );
// Update scale
m_Anims[ m_CurrentState ]->m_ScaleAnim.GetValue( flAnimTime, &m_Geometry.m_Scale );
// Update rotation
m_Anims[ m_CurrentState ]->m_RotationAnim.GetValue( flAnimTime, &m_Geometry.m_Rotation );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHitArea::UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
m_Geometry.CalculateExtents();
bool bDrawHitAreas = false;
if ( !m_Geometry.m_bVisible )
return;
if ( bDrawHitAreas )
{
// Time to invent some render data to draw this thing.
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
int nCount = m_Geometry.m_RelativePositions.Count();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_Geometry.m_RelativePositions[i].x, m_Geometry.m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenpos );
renderGeometry.m_Positions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );;
// Vertex Color
color32 hitAreaColor;
hitAreaColor.r = 255;
hitAreaColor.g = 100;
hitAreaColor.b = 100;
hitAreaColor.a = 255;
renderGeometry.m_VertexColors.AddToTail( hitAreaColor );
}
// TexCoords
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) );
// Triangles
nCount = m_Geometry.m_Triangles.Count();
for ( int i = 0; i < nCount; ++i )
{
renderGeometry.m_Triangles.AddToTail( m_Geometry.m_Triangles[i] );
}
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0;
renderGeometry.m_AnimationRate = 1;
renderGeometry.m_bAnimate = 0;
renderGeometry.m_pImageAlias = NULL;
}
// Now transform our array of positions into local graphic coord system.
int nCount = m_Geometry.m_RelativePositions.Count();
m_ScreenPositions.RemoveAll();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_Geometry.m_RelativePositions[i].x, m_Geometry.m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_Geometry.m_RenderToScreen, screenpos );
m_ScreenPositions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );
}
}
//-----------------------------------------------------------------------------
// Determine if x,y is inside the graphic.
//-----------------------------------------------------------------------------
bool CHitArea::HitTest( int x, int y )
{
if ( !m_bCanAcceptInput ) // note if graphic is invisible, this is false
return false;
if ( m_ScreenPositions.Count() == 0 )
return false;
for ( int i = 0; i < m_Geometry.GetTriangleCount(); ++i )
{
if ( PointTriangleHitTest(
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[0] ],
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[1] ],
m_ScreenPositions[ m_Geometry.m_Triangles[i].m_PointIndex[2] ],
Vector2D( x, y ) ) )
{
//Msg( "%d, %d hit\n", x, y );
return true;
}
}
return false;
}
//-----------------------------------------------------------------------------
// Event that occurs when cursor enters the geometry area
//-----------------------------------------------------------------------------
void CHitArea::OnCursorEnter()
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnCursorEnter\n" );
#endif
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_GAINMOUSEFOCUS" );
}
KeyValues *kvEvent = new KeyValues( "OnMouseFocusGained" );
KeyValues::AutoDelete autodelete( kvEvent );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
g_pGameUISystemMgrImpl->OnMouseFocusGained( this );
}
//-----------------------------------------------------------------------------
// Event that occurs when cursor leaves the geometry area
//-----------------------------------------------------------------------------
void CHitArea::OnCursorExit()
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnCursorExit\n" );
#endif
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_LOSEMOUSEFOCUS" );
}
KeyValues *kvEvent = new KeyValues( "OnMouseFocusLost" );
KeyValues::AutoDelete autodelete( kvEvent );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
g_pGameUISystemMgrImpl->OnMouseFocusLost( this );
}
#define DRAG_THRESHOLD_SQUARED 16
//-----------------------------------------------------------------------------
// Event that occurs when cursor moved inside the geometry area
//-----------------------------------------------------------------------------
void CHitArea::OnCursorMove( const int &cursorX, const int &cursorY )
{
//Msg( "CHitArea::OnCursorMove\n" );
if ( m_bCanStartDragging )
{
m_DragCurrentCursorPos[0] = cursorX;
m_DragCurrentCursorPos[1] = cursorY;
float dx = m_DragCurrentCursorPos[0] - m_DragStartCursorPos[0];
float dy = m_DragCurrentCursorPos[1] - m_DragStartCursorPos[1];
float distance = dx * dx + dy * dy;
if ( distance > DRAG_THRESHOLD_SQUARED )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::Starting dragging\n" );
#endif
OnDragStartCallScriptEvent( cursorX, cursorY );
m_bCanStartDragging = false;
m_IsDragging = true;
}
}
else if ( m_IsDragging )
{
m_DragCurrentCursorPos[0] = cursorX;
m_DragCurrentCursorPos[1] = cursorY;
OnDragCallScriptEvent( cursorX, cursorY );
}
}
//-----------------------------------------------------------------------------
// Event that occurs when left mouse button is pressed
//-----------------------------------------------------------------------------
void CHitArea::OnMouseDown( const ButtonCode_t &code )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnMouseDown\n" );
#endif
// Drag and drop supported for left mouse button only.
// This hit area must be drag enabled to support dragging.
if ( code == MOUSE_LEFT && m_bDragEnabled )
{
m_bCanStartDragging = true;
g_pInputGameUI->GetCursorPos( m_DragStartCursorPos[0], m_DragStartCursorPos[1] );
}
if ( m_pGroup )
{
if ( code == MOUSE_LEFT )
{
m_pGroup->SetState( "AUTO_MOUSELEFTDOWN" );
}
else if ( code == MOUSE_RIGHT )
{
m_pGroup->SetState( "AUTO_MOUSERIGHTDOWN" );
}
else if ( code == MOUSE_MIDDLE )
{
m_pGroup->SetState( "AUTO_MOUSEMIDDLEDOWN" );
}
}
// Check for scripting for this control first.
KeyValues *kvEvent = new KeyValues( "OnMouseDown" );
KeyValues::AutoDelete autodelete( kvEvent );
kvEvent->SetInt( "code", code );
// Always call generic click handler to allow host-overrides
kvEvent->SetName( "OnMouseClicked" );
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
// Call assigned handlers
if ( code == MOUSE_LEFT && !m_OnMouseLeftClickedScriptCommand.IsEmpty() )
{
kvEvent->SetName( m_OnMouseLeftClickedScriptCommand );
bool bExecuted = g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
if ( !bExecuted )
{
Warning( "Unable to find script function %s (assigned to OnMouseLeftClicked)\n", kvEvent->GetName() );
}
}
}
//-----------------------------------------------------------------------------
// Event that occurs when mouse button is released
// Script events should be tied to mouse release events only, not mouse down.
// Scripts should only fire if this graphic has mousefocus.
//-----------------------------------------------------------------------------
void CHitArea::OnMouseUp( const ButtonCode_t &code, bool bFireScripts )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnMouseUp\n" );
#endif
m_bCanStartDragging = false;
if ( m_pGroup )
{
if ( code == MOUSE_LEFT )
{
m_pGroup->SetState( "AUTO_MOUSELEFTUP" );
}
else if ( code == MOUSE_RIGHT )
{
m_pGroup->SetState( "AUTO_MOUSERIGHTUP" );
}
else if ( code == MOUSE_MIDDLE )
{
m_pGroup->SetState( "AUTO_MOUSEMIDDLEUP" );
}
}
if ( m_IsDragging )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::Stopped dragging\n" );
#endif
OnDragStopCallScriptEvent( m_DragCurrentCursorPos[0], m_DragCurrentCursorPos[1] );
}
else if ( bFireScripts )
{
KeyValues *kvEvent = new KeyValues( "OnMouseUp" );
KeyValues::AutoDelete autodelete( kvEvent );
kvEvent->SetInt( "code", code );
// Always call generic click handler to allow host-overrides
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
m_IsDragging = false;
}
//-----------------------------------------------------------------------------
// Event that occurs when mouse button is double clicked
//-----------------------------------------------------------------------------
void CHitArea::OnMouseDoubleClick( const ButtonCode_t &code )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnMouseDoubleClick\n" );
#endif
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_MOUSEDOUBLECLICK" );
}
}
//-----------------------------------------------------------------------------
// Event that occurs when a key is pressed
//-----------------------------------------------------------------------------
void CHitArea::OnKeyDown( const ButtonCode_t &code )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnKeyDown\n" );
#endif
// Pad input gives you pressed and released messages only for buttons
if ( IsJoystickCode( code ) )
{
KeyValues *kvEvent = new KeyValues( "OnButtonPressed" );
KeyValues::AutoDelete autodelete( kvEvent );
kvEvent->SetInt( "code", code );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnKeyCodeTyped( code );
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
else
{
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_KEYDOWN" );
}
}
}
//-----------------------------------------------------------------------------
// Event that occurs when a key is released
//-----------------------------------------------------------------------------
void CHitArea::OnKeyUp( const ButtonCode_t &code )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnKeyUp\n" );
#endif
// Pad input gives you pressed and released messages only for buttons
if ( IsJoystickCode( code ) )
{
KeyValues *kvEvent = new KeyValues( "OnButtonReleased" );
KeyValues::AutoDelete autodelete( kvEvent );
kvEvent->SetInt( "code", code );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnKeyCodeTyped( code );
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
else
{
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_KEYUP" );
}
}
}
//-----------------------------------------------------------------------------
// Event that occurs when a key code is typed
//-----------------------------------------------------------------------------
void CHitArea::OnKeyCodeTyped( const ButtonCode_t &code )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnKeyCodeTyped\n" );
#endif
Assert( g_pInputGameUI->GetKeyFocus() == this );
KeyValues *kvEvent = new KeyValues( "OnKeyTyped" );
KeyValues::AutoDelete autodelete( kvEvent );
kvEvent->SetInt( "code", code );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnKeyCodeTyped( code );
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
//-----------------------------------------------------------------------------
// Event that occurs when a key is typed
//-----------------------------------------------------------------------------
void CHitArea::OnKeyTyped( const wchar_t &unichar )
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnKeyTyped\n" );
#endif
Assert( g_pInputGameUI->GetKeyFocus() == this );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnKeyTyped( unichar );
}
//-----------------------------------------------------------------------------
// Event that occurs when key focus is lost
//-----------------------------------------------------------------------------
void CHitArea::OnLoseKeyFocus()
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnLoseKeyFocus\n" );
#endif
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_LOSEKEYFOCUS" );
}
KeyValues *kvEvent = new KeyValues( "OnKeyFocusLost" );
KeyValues::AutoDelete autodelete( kvEvent );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
//-----------------------------------------------------------------------------
// Event that occurs when key focus is gained
//-----------------------------------------------------------------------------
void CHitArea::OnGainKeyFocus()
{
#if ( DEBUG_INPUT_EVENTS )
Msg( "CHitArea::OnGainKeyFocus\n" );
#endif
if ( m_pGroup )
{
m_pGroup->SetState( "AUTO_GAINKEYFOCUS" );
}
KeyValues *kvEvent = new KeyValues( "OnKeyFocusGained" );
KeyValues::AutoDelete autodelete( kvEvent );
// chain to main system if this graphic doesn't handle it.
g_pGameUISystemMgrImpl->OnGameGraphicScriptEvent( this, kvEvent );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHitArea::OnDragStartCallScriptEvent( const int &cursorX, const int &cursorY )
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHitArea::OnDragCallScriptEvent( const int &cursorX, const int &cursorY )
{
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHitArea::OnDragStopCallScriptEvent( const int &cursorX, const int &cursorY )
{
}
//-----------------------------------------------------------------------------
// Handle focus updating on visibility change.
//-----------------------------------------------------------------------------
void CHitArea::SetVisible( bool bVisible )
{
m_Geometry.m_bVisible = bVisible;
m_bCanAcceptInput = bVisible;
m_bCanStartDragging = false;
if ( bVisible )
{
g_pGameUISystemMgrImpl->ForceFocusUpdate();
}
else
{
// Untested
g_pInputGameUI->GraphicHidden( this );
}
}
//-----------------------------------------------------------------------------
// Handle commands from scripting
//-----------------------------------------------------------------------------
KeyValues * CHitArea::HandleScriptCommand( KeyValues *args )
{
char const *szCommand = args->GetName();
if ( !Q_stricmp( "SetDragEnabled", szCommand ) )
{
m_bDragEnabled = args->GetBool( "dragenabled", 0 );
return NULL;
}
else if ( !Q_stricmp( "SetMouseLeftClickedCommand", szCommand ) )
{
m_OnMouseLeftClickedScriptCommand = args->GetString( "command", "" );
return NULL;
}
if ( !Q_stricmp( "RequestFocus", szCommand ) )
{
g_pGameUISystemMgrImpl->RequestKeyFocus( this, args );
return NULL;
}
return CGameGraphic::HandleScriptCommand( args );
}

View File

@@ -0,0 +1,103 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef HITAREA_H
#define HITAREA_H
#ifdef _WIN32
#pragma once
#endif
#include "gamegraphic.h"
#include "dmxloader/dmxelement.h"
#include "tier1/utlvector.h"
#include "vstdlib/ieventsystem.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CHitArea : public CGameGraphic
{
DECLARE_DMXELEMENT_UNPACK()
public:
CHitArea( const char *pName );
virtual ~CHitArea();
bool Unserialize( CDmxElement *pGraphic );
// Update geometry and execute scripting.
virtual void UpdateGeometry();
virtual void UpdateRenderData( color32 parentColor, CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
virtual bool HitTest( int x, int y );
// Cursor events
// AUTO_GAINMOUSEFOCUS
void OnCursorEnter();
// AUTO_LOSEMOUSEFOCUS
void OnCursorExit();
void OnCursorMove( const int &cursorX, const int &cursorY );
// Mouse events
// AUTO_MOUSELEFTDOWN
// AUTO_MOUSERIGHTDOWN
// AUTO_MOUSEMIDDLEDOWN
void OnMouseDown( const ButtonCode_t &code );
// AUTO_MOUSELEFTUP
// AUTO_MOUSERIGHTUP
// AUTO_MOUSEMIDDLEUP
void OnMouseUp( const ButtonCode_t &code, bool bFireScripts = true );
// AUTO_MOUSEDOUBLECLICK
void OnMouseDoubleClick( const ButtonCode_t &code );
void OnMouseWheel( const int &delta ){}
// Keyboard events
// AUTO_KEYDOWN
void OnKeyDown( const ButtonCode_t &code );
// AUTO_KEYUP
void OnKeyUp( const ButtonCode_t &code );
void OnKeyCodeTyped( const ButtonCode_t &code );
void OnKeyTyped( const wchar_t &unichar );
// AUTO_GAINKEYFOCUS
void OnGainKeyFocus();
// AUTO_LOSEKEYFOCUS
void OnLoseKeyFocus();
// Calls to scripting.
void OnDragStartCallScriptEvent( const int &cursorX, const int &cursorY );
void OnDragCallScriptEvent( const int &cursorX, const int &cursorY );
void OnDragStopCallScriptEvent( const int &cursorX, const int &cursorY );
virtual void SetVisible( bool bVisible );
virtual bool IsHitArea() const { return true; }
virtual KeyValues *HandleScriptCommand( KeyValues *args );
private:
CHitArea();
CUtlVector< Vector2D > m_ScreenPositions;
bool m_bDragEnabled;
bool m_bCanStartDragging;
bool m_IsDragging;
int m_DragStartCursorPos[2];
int m_DragCurrentCursorPos[2];
CUtlString m_OnMouseLeftClickedScriptCommand;
};
#endif // HITAREA_H

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,326 @@
//===== Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $NoKeywords: $
//===========================================================================//
#ifndef INPUTGAMEUI_H
#define INPUTGAMEUI_H
#ifdef _WIN32
#pragma once
#endif
#if !defined( _GAMECONSOLE )
#include <windows.h>
#include <imm.h>
#endif
#include "vgui/iinput.h"
#include "hitarea.h"
#include "keyrepeat.h"
#include "utlvector.h"
#include "utllinkedlist.h"
#include "keyvalues.h"
#include "inputsystem/buttoncode.h"
#include "vgui/cursor.h"
#include "vstdlib/ieventsystem.h"
enum GameUIMouseCodeState_t
{
BUTTON_RELEASED = 0,
BUTTON_PRESSED,
BUTTON_DOUBLECLICKED,
};
namespace vgui
{
typedef unsigned int HInputContext;
#define DEFAULT_INPUT_CONTEXT ((vgui::HInputContext)~0)
}
using namespace vgui;
class CInputGameUI
{
public:
CInputGameUI();
~CInputGameUI();
struct LanguageItem
{
wchar_t shortname[ 4 ];
wchar_t menuname[ 128 ];
int handleValue;
bool active; // true if this is the active language
};
struct ConversionModeItem
{
wchar_t menuname[ 128 ];
int handleValue;
bool active; // true if this is the active conversion mode
};
struct SentenceModeItem
{
wchar_t menuname[ 128 ];
int handleValue;
bool active; // true if this is the active sentence mode
};
void Init();
void RunFrame();
void ProcessEvents();
void Shutdown();
void SetWindowSize( int width, int height );
void PanelDeleted( CHitArea *panel );
void GraphicHidden( CHitArea *focus );
void ForceInputFocusUpdate();
void UpdateMouseFocus(int x, int y);
void SetMouseFocus( CHitArea *newMouseFocus );
// Temp testing until event system can handle destinations.
void OnCursorEnter( CHitArea* const & pTarget );
void OnCursorExit( CHitArea * const & pTarget );
void OnCursorMove( CHitArea * const & pTarget, const int &x, const int &y );
void OnMouseDown( CHitArea * const & pTarget, const ButtonCode_t &code );
void OnMouseUp( CHitArea * const & pTarget, CHitArea * const & pTrap, const ButtonCode_t &code );
void OnMouseDoubleClick( CHitArea * const & pTarget, const ButtonCode_t &code );
void OnMouseWheel( CHitArea * const & pTarget, const int &delta );
void OnKeyDown( CHitArea * const & pTarget, const ButtonCode_t &code );
void OnKeyUp( CHitArea * const & pTarget, const ButtonCode_t &code );
void OnKeyCodeTyped( CHitArea * const & pTarget, const ButtonCode_t &code );
void OnKeyTyped( CHitArea * const & pTarget, const wchar_t &unichar );
void OnLoseKeyFocus( CHitArea * const & pTarget );
void OnGainKeyFocus( CHitArea * const & pTarget );
void SetCursorPos( int x, int y );
void UpdateCursorPosInternal( const int &x, const int &y );
void GetCursorPos( int &x, int &y );
void SetCursorOveride( vgui::HCursor cursor );
vgui::HCursor GetCursorOveride();
void SetKeyFocus( CHitArea *pFocus ); // note this will not post any messages.
CHitArea *GetKeyFocus();
CHitArea *GetCalculatedKeyFocus();
CHitArea *GetMouseOver();
bool WasMousePressed( ButtonCode_t code );
bool WasMouseDoublePressed( ButtonCode_t code );
bool IsMouseDown( ButtonCode_t code );
bool WasMouseReleased( ButtonCode_t code );
bool WasKeyPressed( ButtonCode_t code );
bool IsKeyDown( ButtonCode_t code );
bool WasKeyTyped( ButtonCode_t code );
bool WasKeyReleased( ButtonCode_t code );
void GetKeyCodeText( ButtonCode_t code, char *buf, int buflen );
bool InternalCursorMoved( int x,int y ); //expects input in surface space
bool InternalMousePressed( ButtonCode_t code );
bool InternalMouseDoublePressed( ButtonCode_t code );
bool InternalMouseReleased( ButtonCode_t code );
bool InternalMouseWheeled( int delta );
bool InternalKeyCodePressed( ButtonCode_t code );
void InternalKeyCodeTyped( ButtonCode_t code );
void InternalKeyTyped( wchar_t unichar );
bool InternalKeyCodeReleased( ButtonCode_t code );
void SetKeyCodeState( ButtonCode_t code, bool bPressed );
void SetMouseCodeState( ButtonCode_t code, GameUIMouseCodeState_t state );
void UpdateButtonState( const InputEvent_t &event );
// Creates/ destroys "input" contexts, which contains information
// about which controls have mouse + key focus, for example.
virtual vgui::HInputContext CreateInputContext();
virtual void DestroyInputContext( vgui::HInputContext context );
// Activates a particular input context, use DEFAULT_INPUT_CONTEXT
// to get the one normally used by VGUI
virtual void ActivateInputContext( vgui::HInputContext context );
virtual void PostCursorMessage();
virtual void HandleExplicitSetCursor();
virtual void ResetInputContext( vgui::HInputContext context );
virtual void GetCursorPosition( int &x, int &y );
virtual void SetIMEWindow( void *hwnd );
virtual void *GetIMEWindow();
// Change keyboard layout type
virtual void OnChangeIME( bool forward );
virtual int GetCurrentIMEHandle();
virtual int GetEnglishIMEHandle();
// Returns the Language Bar label (Chinese, Korean, Japanese, Russion, Thai, etc.)
virtual void GetIMELanguageName( wchar_t *buf, int unicodeBufferSizeInBytes );
// Returns the short code for the language (EN, CH, KO, JP, RU, TH, etc. ).
virtual void GetIMELanguageShortCode( wchar_t *buf, int unicodeBufferSizeInBytes );
// Call with NULL dest to get item count
virtual int GetIMELanguageList( LanguageItem *dest, int destcount );
virtual int GetIMEConversionModes( ConversionModeItem *dest, int destcount );
virtual int GetIMESentenceModes( SentenceModeItem *dest, int destcount );
virtual void OnChangeIMEByHandle( int handleValue );
virtual void OnChangeIMEConversionModeByHandle( int handleValue );
virtual void OnChangeIMESentenceModeByHandle( int handleValue );
virtual void OnInputLanguageChanged();
virtual void OnIMEStartComposition();
virtual void OnIMEComposition( int flags );
virtual void OnIMEEndComposition();
virtual void OnIMEShowCandidates();
virtual void OnIMEChangeCandidates();
virtual void OnIMECloseCandidates();
virtual void OnIMERecomputeModes();
virtual int GetCandidateListCount();
virtual void GetCandidate( int num, wchar_t *dest, int destSizeBytes );
virtual int GetCandidateListSelectedItem();
virtual int GetCandidateListPageSize();
virtual int GetCandidateListPageStart();
virtual void SetCandidateWindowPos( int x, int y );
virtual bool GetShouldInvertCompositionString();
virtual bool CandidateListStartsAtOne();
virtual void SetCandidateListPageStart( int start );
// Passes in a keycode which allows hitting other mouse buttons w/o cancelling capture mode
virtual void SetMouseCaptureEx( CHitArea *panel, ButtonCode_t captureStartMouseCode );
// Passes in a keycode which allows hitting other mouse buttons w/o cancelling capture mode
virtual void SetMouseCapture( CHitArea *panel );
virtual CHitArea *GetMouseCapture();
virtual CHitArea *GetMouseFocus();
private:
void InternalSetCompositionString( const wchar_t *compstr );
void InternalShowCandidateWindow();
void InternalHideCandidateWindow();
void InternalUpdateCandidateWindow();
bool PostKeyMessage( KeyValues *message );
void DestroyCandidateList();
void CreateNewCandidateList();
CHitArea *CalculateNewKeyFocus();
void SurfaceSetCursorPos( int x, int y );
void SurfaceGetCursorPos( int &x, int &y );
struct InputContext_t
{
bool _mousePressed[MOUSE_COUNT];
bool _mouseDoublePressed[MOUSE_COUNT];
bool _mouseDown[MOUSE_COUNT];
bool _mouseReleased[MOUSE_COUNT];
bool _keyPressed[BUTTON_CODE_COUNT];
bool _keyTyped[BUTTON_CODE_COUNT];
bool _keyDown[BUTTON_CODE_COUNT];
bool _keyReleased[BUTTON_CODE_COUNT];
CHitArea *_keyFocus;
bool _bKeyTrap; // true if the graphic with keyfocus recieved a down event. Send the up if it got a down.
CHitArea *_oldMouseFocus;
CHitArea *_mouseFocus; // the panel that has the current mouse focus - same as _mouseOver unless _mouseCapture is set
CHitArea *_mouseOver; // the panel that the mouse is currently over, NULL if not over any vgui item
CHitArea *_mouseCapture; // the panel that has currently captured mouse focus
ButtonCode_t m_MouseCaptureStartCode; // The Mouse button which was pressed to initiate mouse capture
CHitArea *_mouseLeftTrap; // the panel that should receive the next mouse left up
CHitArea *_mouseMiddleTrap; // the panel that should receive the next mouse middle up
CHitArea *_mouseRightTrap; // the panel that should receive the next mouse right up
int m_nCursorX;
int m_nCursorY;
int m_nLastPostedCursorX;
int m_nLastPostedCursorY;
int m_nExternallySetCursorX;
int m_nExternallySetCursorY;
bool m_bSetCursorExplicitly;
CUtlVector< CHitArea * > m_KeyCodeUnhandledListeners;
CHitArea *m_pUnhandledMouseClickListener;
bool m_bRestrictMessagesToModalSubTree;
CKeyRepeatHandler m_keyRepeater;
};
void InitInputContext( InputContext_t *pContext );
InputContext_t *GetInputContext( vgui::HInputContext context );
void PanelDeleted( CHitArea *focus, InputContext_t &context);
void GraphicHidden( CHitArea *focus, InputContext_t &context );
vgui::HCursor _cursorOverride;
char *_keyTrans[KEY_LAST];
InputContext_t m_DefaultInputContext;
vgui::HInputContext m_hContext; // current input context
CUtlLinkedList< InputContext_t, vgui::HInputContext > m_Contexts;
#ifndef _GAMECONSOLE
void *_imeWnd;
CANDIDATELIST *_imeCandidates;
#endif
int m_nDebugMessages;
EventQueue_t m_hEventChannel;
int m_nWindowWidth, m_nWindowHeight;
};
extern CInputGameUI *g_pInputGameUI;
bool InputGameUIHandleInputEvent( const InputEvent_t &event );
DEFINE_EVENT1_WITHNAMES( CursorEnterEvent, CHitArea *, pTarget );
DEFINE_EVENT1_WITHNAMES( CursorExitEvent, CHitArea *, pTarget );
DEFINE_EVENT3_WITHNAMES( CursorMoveEvent, CHitArea *, pTarget, int, x, int, y );
DEFINE_EVENT2_WITHNAMES( InternalCursorMoveEvent, int, x, int, y );
DEFINE_EVENT2_WITHNAMES( MouseDownEvent, CHitArea *, pTarget, ButtonCode_t, code );
DEFINE_EVENT3_WITHNAMES( MouseUpEvent, CHitArea *, pTarget, CHitArea *, pTrap, ButtonCode_t, code );
DEFINE_EVENT2_WITHNAMES( MouseDoubleClickEvent, CHitArea *, pTarget, ButtonCode_t, code );
DEFINE_EVENT2_WITHNAMES( MouseWheelEvent, CHitArea *, pTarget, int, delta );
DEFINE_EVENT2_WITHNAMES( KeyDownEvent, CHitArea *, pTarget, ButtonCode_t, code );
DEFINE_EVENT2_WITHNAMES( KeyUpEvent, CHitArea *, pTarget, ButtonCode_t, code );
DEFINE_EVENT2_WITHNAMES( KeyCodeTypedEvent, CHitArea *, pTarget, ButtonCode_t, code );
DEFINE_EVENT2_WITHNAMES( KeyTypedEvent, CHitArea *, pTarget, wchar_t, unichar );
DEFINE_EVENT1_WITHNAMES( GainKeyFocusEvent, CHitArea *, pTarget );
DEFINE_EVENT1_WITHNAMES( LoseKeyFocusEvent, CHitArea *, pTarget );
#endif // INPUTGAMEUI_H

View File

@@ -0,0 +1,174 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "keyrepeat.h"
#include "inputsystem/buttoncode.h"
#include "tier0/dbg.h"
// memdbgon must be the last include file in a .cpp file
#include "tier0/memdbgon.h"
//#define DEBUG_REPEATS
#ifdef DEBUG_REPEATS
#define DbgRepeat(...) ConMsg( __VA_ARGS__ )
#else
#define DbgRepeat(...)
#endif
ButtonCode_t g_iCodesForAliases[FM_NUM_KEYREPEAT_ALIASES] =
{
KEY_XBUTTON_UP,
KEY_XBUTTON_DOWN,
KEY_XBUTTON_LEFT,
KEY_XBUTTON_RIGHT
};
//-----------------------------------------------------------------------------
// Purpose: Map joystick codes to our internal ones
//-----------------------------------------------------------------------------
static int GetIndexForCode( ButtonCode_t code )
{
ButtonCode_t localCode = GetBaseButtonCode( code );
switch ( localCode )
{
case KEY_XBUTTON_DOWN:
case KEY_XSTICK1_DOWN:
case KEY_XSTICK2_DOWN:
return KR_ALIAS_DOWN; break;
case KEY_XBUTTON_UP:
case KEY_XSTICK1_UP:
case KEY_XSTICK2_UP:
return KR_ALIAS_UP; break;
case KEY_XBUTTON_LEFT:
case KEY_XSTICK1_LEFT:
case KEY_XSTICK2_LEFT:
return KR_ALIAS_LEFT; break;
case KEY_XBUTTON_RIGHT:
case KEY_XSTICK1_RIGHT:
case KEY_XSTICK2_RIGHT:
return KR_ALIAS_RIGHT; break;
default:
break;
}
return -1;
}
//-----------------------------------------------------------------------------
CKeyRepeatHandler::CKeyRepeatHandler()
{
Reset();
for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ )
{
m_flRepeatTimes[i] = 0.16;
}
}
//-----------------------------------------------------------------------------
// Purpose: Clear all state
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::Reset()
{
DbgRepeat( "KeyRepeat: Reset\n" );
memset( m_bAliasDown, 0, sizeof( m_bAliasDown ) );
m_bHaveKeyDown = false;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::KeyDown( ButtonCode_t code )
{
int joyStick = GetJoystickForCode( code );
int iIndex = GetIndexForCode(code);
if ( iIndex == -1 )
return;
if ( m_bAliasDown[ joyStick ][ iIndex ] )
return;
DbgRepeat( "KeyRepeat: KeyDown %d(%d)\n", joyStick, iIndex );
Reset();
m_bAliasDown[ joyStick ][ iIndex ] = true;
m_flNextKeyRepeat[ joyStick ] = Plat_FloatTime() + 0.4;
m_bHaveKeyDown = true;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::KeyUp( ButtonCode_t code )
{
int joyStick = GetJoystickForCode( code );
int iIndex = GetIndexForCode(code);
if ( iIndex == -1 )
return;
DbgRepeat( "KeyRepeat: KeyUp %d(%d)\n", joyStick, iIndex );
m_bAliasDown[ joyStick ][ iIndex ] = false;
m_bHaveKeyDown = false;
for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ )
{
for ( int j = 0; j < MAX_JOYSTICKS; j++ )
{
if ( m_bAliasDown[ j ][ i ] )
{
m_bHaveKeyDown = true;
break;
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
ButtonCode_t CKeyRepeatHandler::KeyRepeated( void )
{
if ( IsPC() )
return BUTTON_CODE_NONE;
if ( !m_bHaveKeyDown )
return BUTTON_CODE_NONE;
float currentTime = Plat_FloatTime();
for ( int j = 0; j < MAX_JOYSTICKS; j++ )
{
if ( m_flNextKeyRepeat[ j ] < currentTime )
{
for ( int i = 0; i < FM_NUM_KEYREPEAT_ALIASES; i++ )
{
if ( m_bAliasDown[ j ][ i ] )
{
m_flNextKeyRepeat[ j ] = currentTime + m_flRepeatTimes[i];
DbgRepeat( "KeyRepeat: Repeat %d(%d)\n", j, i );
return ButtonCodeToJoystickButtonCode( g_iCodesForAliases[i], j );
}
}
}
}
return BUTTON_CODE_NONE;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CKeyRepeatHandler::SetKeyRepeatTime( ButtonCode_t code, float flRepeat )
{
int iIndex = GetIndexForCode(code);
Assert( iIndex != -1 );
m_flRepeatTimes[ iIndex ] = flRepeat;
}

View File

@@ -0,0 +1,46 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef KEYREPEAT_H
#define KEYREPEAT_H
#ifdef _WIN32
#pragma once
#endif
#include "inputsystem/buttoncode.h"
enum KEYREPEAT_ALIASES
{
KR_ALIAS_UP,
KR_ALIAS_DOWN,
KR_ALIAS_LEFT,
KR_ALIAS_RIGHT,
FM_NUM_KEYREPEAT_ALIASES,
};
class CKeyRepeatHandler
{
public:
CKeyRepeatHandler();
void Reset();
void KeyDown( ButtonCode_t code );
void KeyUp( ButtonCode_t code );
ButtonCode_t KeyRepeated();
void SetKeyRepeatTime( ButtonCode_t code, float flRepeat );
private:
bool m_bAliasDown[MAX_JOYSTICKS][FM_NUM_KEYREPEAT_ALIASES];
float m_flRepeatTimes[FM_NUM_KEYREPEAT_ALIASES];
float m_flNextKeyRepeat[MAX_JOYSTICKS];
bool m_bHaveKeyDown;
};
#endif // KEYREPEAT_H

View File

@@ -0,0 +1,30 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef GAMEGRAPHIC_H
#define GAMEGRAPHIC_H
#ifdef _WIN32
#pragma once
#endif
#include "game_controls/uiquadinfo.h"
#include "tier1/utlvector.h"
//-----------------------------------------------------------------------------
// A class that contains a texture.
//-----------------------------------------------------------------------------
class IGameGraphic
{
public:
virtual void GetQuads( CUtlVector<CQuadInfo> &quadInfo ) = 0;
};
#endif // GAMEGRAPHIC_H

View File

@@ -0,0 +1,223 @@
//=========== (C) Copyright 1999 Valve, L.L.C. All rights reserved. ===========
//
// The copyright to the contents herein is the property of Valve, L.L.C.
// The contents may be used and/or copied only with the written permission of
// Valve, L.L.C., or in accordance with the terms and conditions stipulated in
// the agreement/contract under which the contents have been supplied.
//
// $Header: $
// $NoKeywords: $
//
//=============================================================================
#include "textdisplay.h"
#include "gameuisystemmgr.h"
#include "gameuisystem.h"
#include "gametext.h"
#include "tier1/utlbuffer.h"
#define VERTICAL_SPACING 20
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CTextDisplay::CTextDisplay()
{
m_nXOffset = 10;
m_nYOffset = 10;
m_nXStaticOffset = 10;
m_nYStaticOffset = 10;
m_bIsInitialized = false;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::Init( IGameUISystem *pMenu )
{
if ( m_bIsInitialized )
return;
Vector2D stageSize(0, 0);
m_pMenu = ( CGameUISystem * ) pMenu;
Assert( m_pMenu );
m_pMenu->GetStageSize( stageSize );
m_nXOffset = (-stageSize.x/2) + 10;
m_nYOffset = (-stageSize.y/2) + 10;
m_nXStaticOffset = (-stageSize.x/2) + 500;
m_nYStaticOffset = (-stageSize.y/2) + 10;
m_bIsInitialized = true;
}
//-----------------------------------------------------------------------------
// Text that doesn't change every frame.
//-----------------------------------------------------------------------------
void CTextDisplay::AddStaticText( const char* pFmt, ... )
{
va_list args;
CUtlBuffer message;
va_start( args, pFmt );
message.VaPrintf( pFmt, args );
va_end( args );
char strMessage[255];
message.GetString( strMessage, 255 );
CGameText *pNewInfo = new CGameText( "staticText" );
pNewInfo->SetFont( "Default" );
pNewInfo->SetText( strMessage );
pNewInfo->SetCenter( m_nXStaticOffset, m_nYStaticOffset );
m_nYStaticOffset += VERTICAL_SPACING;
m_pStaticText.AddToTail( pNewInfo );
if ( m_pMenu )
{
m_pMenu->Definition().AddGraphicToLayer( pNewInfo, SUBLAYER_FONT );
}
}
//-----------------------------------------------------------------------------
// Text that doesn't change every frame.
//-----------------------------------------------------------------------------
void CTextDisplay::AddStaticText( int xPos, int yPos, const char* pFmt, ... )
{
va_list args;
CUtlBuffer message;
va_start( args, pFmt );
message.VaPrintf( pFmt, args );
va_end( args );
char strMessage[255];
message.GetString( strMessage, 255 );
CGameText *pNewInfo = new CGameText( "staticText" );
pNewInfo->SetFont( "Default" );
pNewInfo->SetText( strMessage );
pNewInfo->SetCenter( xPos, yPos );
m_pStaticText.AddToTail( pNewInfo );
if ( m_pMenu )
{
m_pMenu->Definition().AddGraphicToLayer( pNewInfo, SUBLAYER_FONT );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::PrintMsg( const char* pFmt, ... )
{
va_list args;
CUtlBuffer message;
va_start( args, pFmt );
message.VaPrintf( pFmt, args );
va_end( args );
char strMessage[255];
message.GetString( strMessage, 255 );
CGameText *pNewInfo = new CGameText( "msgText" );
pNewInfo->SetFont( "Default" );
pNewInfo->SetText( strMessage );
pNewInfo->SetCenter( m_nXOffset, m_nYOffset );
m_nYOffset += VERTICAL_SPACING;
m_pStatsText.AddToTail( pNewInfo );
if ( m_pMenu )
{
m_pMenu->Definition().AddGraphicToLayer( pNewInfo, SUBLAYER_FONT );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::PrintMsg( int xPos, int yPos, const char* pFmt, ... )
{
va_list args;
CUtlBuffer message;
va_start( args, pFmt );
message.VaPrintf( pFmt, args );
va_end( args );
char strMessage[255];
message.GetString( strMessage, 255 );
CGameText *pNewInfo = new CGameText( "msgText" );
pNewInfo->SetFont( "Default" );
pNewInfo->SetText( strMessage );
pNewInfo->SetCenter( xPos, yPos );
m_pStatsText.AddToTail( pNewInfo );
if ( m_pMenu )
{
m_pMenu->Definition().AddGraphicToLayer( pNewInfo, SUBLAYER_FONT );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::ClearStaticText()
{
if ( m_pMenu )
{
for ( int i = 0; i < m_pStaticText.Count(); ++i )
{
m_pMenu->Definition().RemoveGraphic( m_pStaticText[i] );
}
m_pStaticText.RemoveAll();
Vector2D stageSize(0, 0);
m_pMenu->GetStageSize( stageSize );
m_nYStaticOffset = (-stageSize.y/2) + 10;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::FinishFrame()
{
if ( m_pMenu )
{
for ( int i = 0; i < m_pStatsText.Count(); ++i )
{
m_pMenu->Definition().RemoveGraphic( m_pStatsText[i] );
delete m_pStatsText[i];
m_pStatsText[i] = NULL;
}
m_pStatsText.RemoveAll();
Vector2D stageSize(0, 0);
m_pMenu->GetStageSize( stageSize );
m_nYOffset = (-stageSize.y/2) + 10;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CTextDisplay::Shutdown()
{
FinishFrame();
ClearStaticText();
m_bIsInitialized = false;
}

View File

@@ -0,0 +1,479 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "typedlog.h"
#include "dmxloader/dmxelement.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
// Helper function for unserializing value and time log arrays
//-----------------------------------------------------------------------------
template<>
bool CTypedLog< Color >::UnSerializeValues( CDmxAttribute *pLogValues, CDmxAttribute *pLogTimes )
{
Assert(0);
return false;
}
template< typename T >
bool CTypedLog< T >::UnSerializeValues( CDmxAttribute *pLogValues, CDmxAttribute *pLogTimes )
{
const CUtlVector< T > &logvalues = pLogValues->GetArray< T >();
const CUtlVector< DmeTime_t > &logtimes = pLogTimes->GetArray< DmeTime_t >();
int nCount = logvalues.Count();
Assert( nCount == logtimes.Count() );
for ( int i = 0; i < nCount; ++i )
{
m_values.AddToTail( logvalues[i] );
m_times.AddToTail( logtimes[i] );
}
return true;
}
//-----------------------------------------------------------------------------
// Read in the log values and timestamps
// Color is a special case because we are reading from a Color into color32
//-----------------------------------------------------------------------------
template<>
bool CTypedLog< color32 >::Unserialize( CDmxElement *pElement )
{
m_fAnimationRateMultiplier = pElement->GetValue<float>( "animationrate" );
m_bLoop = pElement->GetValue<bool>( "loop" );
m_UseDefaultValue = pElement->GetValue<bool>( "usedefault" );
m_DefaultValue = pElement->GetValue<Color>( "defaultvalue" ).ToColor32();
CDmxAttribute *pLogValues = pElement->GetAttribute( "logvalues" );
if ( !pLogValues )
{
return true;
}
// There might be no entries.
if ( pLogValues->GetType() != AT_COLOR_ARRAY )
{
return true;
}
CDmxAttribute *pLogTimes = pElement->GetAttribute( "logtimes" );
if ( !pLogTimes )
{
// If there are no logtime entry, and there is a log value entry, there is an error.
return false;
}
if ( pLogTimes->GetType() != AT_TIME_ARRAY )
{
// If there are no log times to go with the values.. there is an error.
return false;
}
if ( m_UseDefaultValue )
{
Warning( "Warning: Possible unintended behavior: CTypedLog is set to use a default value when there are log entries.\n" );
}
const CUtlVector< Color > &logvalues = pLogValues->GetArray< Color >();
const CUtlVector< DmeTime_t > &logtimes = pLogTimes->GetArray< DmeTime_t >();
int nCount = logvalues.Count();
Assert( nCount == logtimes.Count() );
for ( int i = 0; i < nCount; ++i )
{
m_values.AddToTail( logvalues[i].ToColor32() );
m_times.AddToTail( logtimes[i] );
}
return true;
}
template<>
bool CTypedLog< float >::Unserialize( CDmxElement *pElement )
{
m_fAnimationRateMultiplier = pElement->GetValue<float>( "animationrate" );
m_bLoop = pElement->GetValue<bool>( "loop" );
m_UseDefaultValue = pElement->GetValue<bool>( "usedefault" );
m_DefaultValue = pElement->GetValue<float>( "defaultvalue" );
CDmxAttribute *pLogValues = pElement->GetAttribute( "logvalues" );
if ( !pLogValues )
{
return true;
}
// There might be no entries.
if ( pLogValues->GetType() != AT_FLOAT_ARRAY )
{
return true;
}
CDmxAttribute *pLogTimes = pElement->GetAttribute( "logtimes" );
if ( !pLogTimes )
{
return false;
}
if ( pLogTimes->GetType() != AT_TIME_ARRAY )
{
return false;
}
if ( m_UseDefaultValue )
{
Warning( "Warning: Possible unintended behavior: CTypedLog is set to use a default value when there are log entries.\n" );
}
return UnSerializeValues( pLogValues, pLogTimes );
}
template<>
bool CTypedLog< Vector2D >::Unserialize( CDmxElement *pElement )
{
m_fAnimationRateMultiplier = pElement->GetValue<float>( "animationrate" );
m_bLoop = pElement->GetValue<bool>( "loop" );
m_UseDefaultValue = pElement->GetValue<bool>( "usedefault" );
m_DefaultValue = pElement->GetValue<Vector2D>( "defaultvalue" );
CDmxAttribute *pLogValues = pElement->GetAttribute( "logvalues" );
if ( !pLogValues )
{
return true;
}
// There might be no entries.
if ( pLogValues->GetType() != AT_VECTOR2_ARRAY )
{
return true;
}
CDmxAttribute *pLogTimes = pElement->GetAttribute( "logtimes" );
if ( !pLogTimes )
{
return false;
}
// There might be no entries.
if ( pLogTimes->GetType() != AT_TIME_ARRAY )
{
return false;
}
if ( m_UseDefaultValue )
{
Warning( "Warning: Possible unintended behavior: CTypedLog is set to use a default value when there are log entries.\n" );
}
return UnSerializeValues( pLogValues, pLogTimes );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template<>
bool CTypedLog<CUtlString>::Unserialize( CDmxElement *pElement )
{
m_fAnimationRateMultiplier = pElement->GetValue<float>( "animationrate" );
m_bLoop = pElement->GetValue<bool>( "loop" );
m_UseDefaultValue = pElement->GetValue<bool>( "usedefault" );
m_DefaultValue = pElement->GetValue<CUtlString>( "defaultvalue" );
CDmxAttribute *pLogValues = pElement->GetAttribute( "logvalues" );
if ( !pLogValues )
{
return true;
}
// There might be no entries.
if ( pLogValues->GetType() != AT_STRING_ARRAY )
{
return true;
}
CDmxAttribute *pLogTimes = pElement->GetAttribute( "logtimes" );
if ( !pLogTimes )
{
return false;
}
// There might be no entries.
if ( pLogTimes->GetType() != AT_TIME_ARRAY )
{
return false;
}
if ( m_UseDefaultValue )
{
Warning( "Warning: Possible unintended behavior: CTypedLog is set to use a default value when there are log entries.\n" );
}
return UnSerializeValues( pLogValues, pLogTimes );
}
//-----------------------------------------------------------------------------
// All unserialization is specialized in order to get the values array type correctly.
//-----------------------------------------------------------------------------
template< class T >
bool CTypedLog<T>::Unserialize( CDmxElement *pElement )
{
Assert( 0 );
return false;
}
//-----------------------------------------------------------------------------
// Given a time, return the log index to use
//-----------------------------------------------------------------------------
template< class T >
int CTypedLog<T>::GetValueForTime( DmeTime_t time )
{
int nNumEntries = m_values.Count();
if ( ( nNumEntries == 1 ) || ( time == DMETIME_ZERO ) )
{
return 0;
}
else
{
for ( int i = 0; i < nNumEntries; ++i )
{
if ( time > m_times[i] )
{
continue;
}
else
{
return i;
}
}
return nNumEntries - 1;
}
}
//-----------------------------------------------------------------------------
// Given a time, adjust it for animation rate and looping.
// Return true if we are past the end of the last log time.
// On the game side we do not have channels to take care of doing this so do it now.
//-----------------------------------------------------------------------------
template< class T >
void CTypedLog<T>::AdjustTimeByLogAttributes( DmeTime_t &time )
{
time *= m_fAnimationRateMultiplier;
DmeTime_t totalTime = m_times[m_values.Count()-1];
if ( m_bLoop )
{
// Put time inside our duration.
time = time % totalTime;
}
// If we've run past the end of the log, clamp it to the end for
// ease of value retrieval.
if ( time > totalTime )
{
time = totalTime;
}
}
//-----------------------------------------------------------------------------
// Given a time, return the log value.
//-----------------------------------------------------------------------------
template<>
void CTypedLog<color32>::GetValue( DmeTime_t time, color32 *pOutValue )
{
if ( m_UseDefaultValue )
{
*pOutValue = m_DefaultValue;
return;
}
int nNumEntries = m_values.Count();
if ( nNumEntries == 0 )
{
return;
}
AdjustTimeByLogAttributes( time );
int i = GetValueForTime( time );
if ( i == 0 )
{
*pOutValue = m_values[0];
return;
}
// Linear interp for now.
Assert( i != 0 );
DmeTime_t startTimeStamp = m_times[i-1];
DmeTime_t endTimeStamp = m_times[i];
DmeTime_t timeIntoInterval = time - startTimeStamp;
DmeTime_t timeOfInterval = endTimeStamp - startTimeStamp;
float dt = timeIntoInterval / timeOfInterval;
pOutValue->r = m_values[ i-1 ].r * ( 1.0f - dt ) + m_values[ i ].r * dt;
pOutValue->g = m_values[ i-1 ].g * ( 1.0f - dt ) + m_values[ i ].g * dt;
pOutValue->b = m_values[ i-1 ].b * ( 1.0f - dt ) + m_values[ i ].b * dt;
pOutValue->a = m_values[ i-1 ].a * ( 1.0f - dt ) + m_values[ i ].a * dt;
}
template<>
void CTypedLog< float >::GetValue( DmeTime_t time, float *pOutValue )
{
if ( m_UseDefaultValue )
{
*pOutValue = m_DefaultValue;
return;
}
int nNumEntries = m_values.Count();
if ( nNumEntries == 0 )
{
return;
}
AdjustTimeByLogAttributes( time );
int i = GetValueForTime( time );
if ( i == 0 )
{
*pOutValue = m_values[0];
return;
}
// Now get distance between the two log entries
// Linear interp for now.
float startVal = m_values[i-1];
float endVal = m_values[i];
float distance = endVal - startVal;
Assert( i != 0 );
DmeTime_t startTimeStamp = m_times[i-1];
DmeTime_t endTimeStamp = m_times[i];
DmeTime_t timeIntoInterval = time - startTimeStamp;
DmeTime_t timeOfInterval = endTimeStamp - startTimeStamp;
float dt = timeIntoInterval / timeOfInterval;
*pOutValue = startVal + distance * dt;
}
template<>
void CTypedLog< Vector2D >::GetValue( DmeTime_t time, Vector2D *pOutValue )
{
if ( m_UseDefaultValue )
{
*pOutValue = m_DefaultValue;
return;
}
int nNumEntries = m_values.Count();
if ( nNumEntries == 0 )
{
return;
}
AdjustTimeByLogAttributes( time );
int i = GetValueForTime( time );
if ( i == 0 )
{
*pOutValue = m_values[0];
return;
}
// Now get distance between the two log entries
// Linear interp for now.
Vector2D distance;
Vector2DSubtract( m_values[i], m_values[i-1], distance );
Assert( i != 0 );
DmeTime_t startTimeStamp = m_times[i-1];
DmeTime_t endTimeStamp = m_times[i];
DmeTime_t timeIntoInterval = time - startTimeStamp;
DmeTime_t timeOfInterval = endTimeStamp - startTimeStamp;
float dt = timeIntoInterval / timeOfInterval;
pOutValue->x = m_values[i-1].x + distance.x * dt;
pOutValue->y = m_values[i-1].y + distance.y * dt;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template<>
void CTypedLog<CUtlString>::GetValue( DmeTime_t time, CUtlString *pOutValue )
{
if ( m_UseDefaultValue )
{
*pOutValue = m_DefaultValue;
return;
}
int nNumEntries = m_values.Count();
if ( nNumEntries == 0 )
{
return;
}
time *= m_fAnimationRateMultiplier;
AdjustTimeByLogAttributes( time );
int i = GetValueForTime( time );
*pOutValue = m_values[i];
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
template< class T >
void CTypedLog<T>::GetValue( DmeTime_t time, T *pOutValue )
{
Assert(0);
}

View File

@@ -0,0 +1,75 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef TYPEDLOG_H
#define TYPEDLOG_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
#include "tier1/timeutils.h"
class CDmxElement;
class CDmxAttribute;
template< class T >
class CTypedLog
{
public:
CTypedLog()
{
m_UseDefaultValue = false;
m_bLoop = false;
m_fAnimationRateMultiplier = 1.0f;
}
//~CTypedLog();
bool Unserialize( CDmxElement *pElement );
void GetValue( DmeTime_t time, T *pOutValue );
bool HasValues()
{
return ( !IsEmpty() || UsesDefaultValue() );
}
bool IsEmpty(){ return ( m_values.Count() == 0 ); }
bool UsesDefaultValue(){ return m_UseDefaultValue; }
bool IsDone( DmeTime_t time )
{
int nNumEntries = m_values.Count();
if ( nNumEntries == 0 )
{
return true;
}
else if ( time >= m_times[nNumEntries-1] )
{
return true;
}
return false;
}
private:
bool UnSerializeValues( CDmxAttribute *pLogValues, CDmxAttribute *pLogTimes );
void AdjustTimeByLogAttributes( DmeTime_t &time );
int GetValueForTime( DmeTime_t time );
CUtlVector< T > m_values;
CUtlVector< DmeTime_t > m_times;
float m_fAnimationRateMultiplier;
bool m_bLoop;
bool m_UseDefaultValue;
T m_DefaultValue;
};
#endif // COLORLOG_H

View File

@@ -0,0 +1,659 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#include "uigeometry.h"
#include "materialsystem/imaterialsystem.h"
#include "mathlib/vector.h"
#include "gamegraphic.h"
#include "graphicgroup.h"
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
CGeometry::CGeometry()
{
m_Center.x = 0;
m_Center.y = 0;
m_Scale.x = 1;
m_Scale.y = 1;
m_Rotation = 0;
m_Color.r = 255;
m_Color.g = 255;
m_Color.b = 255;
m_Color.a = 255;
m_TopColor.r = 255;
m_TopColor.g = 255;
m_TopColor.b = 255;
m_TopColor.a = 255;
m_BottomColor.r = 255;
m_BottomColor.g = 255;
m_BottomColor.b = 255;
m_BottomColor.a = 255;
m_bHorizontalGradient = false;
m_SheetSequenceNumber = 0;
m_AnimationRate = 1;
m_Sublayer = -1;
m_bMaintainAspectRatio = true;
m_bVisible = true;
m_AnimStartTime = DMETIME_ZERO;
m_bAnimate = false;
m_bDirtyExtents = false;
}
//-----------------------------------------------------------------------------
// Rendering helper
// Calculate a matrix that will transform the points of the geometry, which are
// currently relative to the center, into screen coords.
//-----------------------------------------------------------------------------
void CGeometry::UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup )
{
Assert( pGroup );
if ( !pGroup->IsStageGroup() )
{
if ( pGroup->GetVisible() == false )
{
Assert( m_bVisible == pGroup->GetVisible() );
}
}
if ( !m_bVisible )
return;
// Update positions relative to the center, texture coords, and vertex colors
// If the group maintains aspect ratio it will already have handled this in its transform update.
Vector2D center;
bool bUseMaintainedMatrix = m_bMaintainAspectRatio && !pGroup->MaintainAspectRatio();
if ( bUseMaintainedMatrix )
{
// If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
// Note this is not accounting for groups or rotations.
matrix3x4_t screenScalemat;
SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat );
Vector centerVec( m_Center.x, m_Center.y, 0 );
Vector centerInScreen;
VectorTransform( centerVec, screenScalemat, centerInScreen );
// Remove the uniform scale component from the center because it will come back in GetRenderTransform()
float scaleToUse;
if ( stageRenderInfo.parentScale.x > stageRenderInfo.parentScale.y )
{
scaleToUse = stageRenderInfo.parentScale.y;
}
else
{
scaleToUse = stageRenderInfo.parentScale.x;
}
SetScaleMatrix( 1/scaleToUse, 1/scaleToUse, 1, screenScalemat );
Vector tempCenter;
VectorTransform( centerInScreen, screenScalemat, tempCenter );
center.x = tempCenter.x;
center.y = tempCenter.y;
/* old version.
// If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
matrix3x4_t screenScalemat;
SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat );
Vector centerVec( m_Center.x, m_Center.y, 0 );
Vector centerInScreen;
VectorTransform( centerVec, screenScalemat, centerInScreen );
center.x = centerInScreen.x;
center.y = centerInScreen.y;
*/
}
else
{
center = m_Center;
}
matrix3x4_t transmat;
Vector position( center.x, center.y, 0 );
SetIdentityMatrix( transmat );
PositionMatrix( position, transmat );
matrix3x4_t scalemat;
SetScaleMatrix( m_Scale.x, m_Scale.y, 1, scalemat );
matrix3x4_t rotmat;
Vector axis( 0, 0, 1 );
MatrixBuildRotationAboutAxis( axis, m_Rotation, rotmat );
matrix3x4_t temp;
MatrixMultiply( rotmat, scalemat, temp );
matrix3x4_t rawToLocal;
MatrixMultiply( transmat, temp, rawToLocal );
matrix3x4_t groupToScreen;
// Use the matrix that doesn't contain any scale changes if we should
pGroup->GetRenderTransform( groupToScreen, bUseMaintainedMatrix );
MatrixMultiply( groupToScreen, rawToLocal, m_RenderToScreen );
if ( m_bDirtyExtents )
{
CalculateExtentsMatrix( stageRenderInfo, pGroup );
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGeometry::UpdateRenderData( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex )
{
if ( !m_bVisible )
return;
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
// Now transform our array of positions into local graphic coord system.
int nCount = m_RelativePositions.Count();
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_RelativePositions[i].x, m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_RenderToScreen, screenpos );
renderGeometry.m_Positions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );;
// TexCoord
renderGeometry.m_TextureCoords.AddToTail( m_TextureCoords[i] );
// Vertex Color
renderGeometry.m_VertexColors.AddToTail( m_VertexColors[i] );
}
// Triangles
nCount = m_Triangles.Count();
for ( int i = 0; i < nCount; ++i )
{
renderGeometry.m_Triangles.AddToTail( m_Triangles[i] );
}
// Anim Info
renderGeometry.m_SheetSequenceNumber = m_SheetSequenceNumber;
renderGeometry.m_AnimationRate = m_AnimationRate;
renderGeometry.m_bAnimate = m_bAnimate;
renderGeometry.m_AnimStartTime = m_AnimStartTime;
renderGeometry.m_pImageAlias = NULL;
CalculateExtents();
}
//-----------------------------------------------------------------------------
// Calculate the rectangular extents of this graphic.
//-----------------------------------------------------------------------------
void CGeometry::CalculateExtentsMatrix( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup )
{
Assert( pGroup );
// Update positions relative to the center, texture coords, and vertex colors
// If the group maintains aspect ratio it will already have handled this in its transform update.
Vector2D center;
bool bUseMaintainedMatrix = m_bMaintainAspectRatio && !pGroup->MaintainAspectRatio();
if ( bUseMaintainedMatrix )
{
// If this is the case we transform the center to screen coords first.
// Then take into account any size scaling in the scalemat
matrix3x4_t screenScalemat;
SetScaleMatrix( stageRenderInfo.parentScale.x, stageRenderInfo.parentScale.y, 1, screenScalemat );
Vector centerVec( m_Center.x, m_Center.y, 0 );
Vector centerInScreen;
VectorTransform( centerVec, screenScalemat, centerInScreen );
center.x = centerInScreen.x;
center.y = centerInScreen.y;
}
else
{
center = m_Center;
}
matrix3x4_t transmat;
Vector position( center.x, center.y, 0 );
SetIdentityMatrix( transmat );
PositionMatrix( position, transmat );
// TODO: account for scaling anims?
matrix3x4_t scalemat;
SetScaleMatrix( m_Scale.x, m_Scale.y, 1, scalemat );
// Rotation is ignored.
matrix3x4_t rotmat;
Vector axis( 0, 0, 1 );
MatrixBuildRotationAboutAxis( axis, 0, rotmat );
matrix3x4_t temp;
MatrixMultiply( rotmat, scalemat, temp );
matrix3x4_t rawToLocal;
MatrixMultiply( transmat, temp, rawToLocal );
matrix3x4_t groupToScreen;
// Use the matrix that doesn't contain any scale changes if we should
pGroup->GetRenderTransform( groupToScreen, bUseMaintainedMatrix );
MatrixMultiply( groupToScreen, rawToLocal, m_ExtentsMatrix );
}
//-----------------------------------------------------------------------------
// Calculate the rectangular extents of this graphic.
//-----------------------------------------------------------------------------
void CGeometry::CalculateExtents()
{
if ( !m_bDirtyExtents )
return;
// Now transform our array of positions into local graphic coord system.
int nCount = m_RelativePositions.Count();
CUtlVector< Vector2D > screenPositions;
for ( int i = 0; i < nCount; ++i )
{
// Position
Vector relativePosition( m_RelativePositions[i].x, m_RelativePositions[i].y, 0 );
Vector screenpos;
VectorTransform( relativePosition, m_ExtentsMatrix, screenpos );
screenPositions.AddToTail( Vector2D( screenpos.x, screenpos.y ) );;
}
// left most position is x.
m_Extents.m_TopLeft.x = INT_MAX;
for ( int i = 0; i < screenPositions.Count(); ++i )
{
if ( m_Extents.m_TopLeft.x > screenPositions[i].x )
m_Extents.m_TopLeft.x = screenPositions[i].x;
}
// top most position is y.
m_Extents.m_TopLeft.y = INT_MAX;
for ( int i = 0; i < screenPositions.Count(); ++i )
{
if ( m_Extents.m_TopLeft.y > screenPositions[i].y )
m_Extents.m_TopLeft.y = screenPositions[i].y;
}
// right most position is x
m_Extents.m_BottomRight.x = INT_MIN;
for ( int i = 0; i < screenPositions.Count(); ++i )
{
if ( m_Extents.m_BottomRight.x < screenPositions[i].x )
m_Extents.m_BottomRight.x = screenPositions[i].x;
}
// bottom most position is y
m_Extents.m_BottomRight.y = INT_MIN;
for ( int i = 0; i < screenPositions.Count(); ++i )
{
if ( m_Extents.m_BottomRight.y < screenPositions[i].y )
m_Extents.m_BottomRight.y = screenPositions[i].y;
}
m_bDirtyExtents = false;
}
//-----------------------------------------------------------------------------
// Return the rectangular bounds of this object
//-----------------------------------------------------------------------------
void CGeometry::GetBounds( Rect_t &bounds )
{
bounds.x = m_Extents.m_TopLeft.x;
bounds.y = m_Extents.m_TopLeft.x;
bounds.width = m_Extents.m_BottomRight.x - m_Extents.m_TopLeft.x;
bounds.height = m_Extents.m_BottomRight.y - m_Extents.m_TopLeft.y;
}
//-----------------------------------------------------------------------------
// Purpose: Set the vertex colors of the graphic using the base color and the gradient colors.
//-----------------------------------------------------------------------------
void CGeometry::SetResultantColor( color32 parentColor )
{
SetResultantColor( true, parentColor );
SetResultantColor( false, parentColor );
}
//-----------------------------------------------------------------------------
// Purpose: Set the vertex colors of the graphic using the base color and the gradient colors.
//-----------------------------------------------------------------------------
void CGeometry::SetResultantColor( bool bTop, color32 parentColor )
{
if ( bTop )
{
color32 localColor;
localColor.r = (int)( (float)m_TopColor.r * (float)(m_Color.r/255.0) );
localColor.g = (int)( (float)m_TopColor.g * (float)(m_Color.g/255.0) );
localColor.b = (int)( (float)m_TopColor.b * (float)(m_Color.b/255.0) );
localColor.a = (int)( (float)m_TopColor.a * (float)(m_Color.a/255.0) );
color32 resultantColor;
resultantColor.r = (int)( (float)localColor.r * (float)(parentColor.r/255.0) );
resultantColor.g = (int)( (float)localColor.g * (float)(parentColor.g/255.0) );
resultantColor.b = (int)( (float)localColor.b * (float)(parentColor.b/255.0) );
resultantColor.a = (int)( (float)localColor.a * (float)(parentColor.a/255.0) );
SetTopVerticesColor( resultantColor );
}
else
{
color32 localColor;
localColor.r = (int)( (float)m_BottomColor.r * (float)(m_Color.r/255.0) );
localColor.g = (int)( (float)m_BottomColor.g * (float)(m_Color.g/255.0) );
localColor.b = (int)( (float)m_BottomColor.b * (float)(m_Color.b/255.0) );
localColor.a = (int)( (float)m_BottomColor.a * (float)(m_Color.a/255.0) );
color32 resultantColor;
resultantColor.r = (int)( (float)localColor.r * (float)(parentColor.r/255.0) );
resultantColor.g = (int)( (float)localColor.g * (float)(parentColor.g/255.0) );
resultantColor.b = (int)( (float)localColor.b * (float)(parentColor.b/255.0) );
resultantColor.a = (int)( (float)localColor.a * (float)(parentColor.a/255.0) );
SetBottomVerticesColor( resultantColor );
}
}
//-----------------------------------------------------------------------------
// Note corner colors will be stomped if the base graphic's color changes.
//-----------------------------------------------------------------------------
void CGeometry::SetTopVerticesColor( color32 c )
{
if ( m_bHorizontalGradient )
{
for ( int i = 0; i < m_VertexColors.Count(); i += 4 )
{
m_VertexColors[i] = c;
m_VertexColors[i+3] = c;
}
}
else
{
for ( int i = 0; i < m_VertexColors.Count(); i += 4 )
{
m_VertexColors[i] = c;
m_VertexColors[i+1] = c;
}
}
}
//-----------------------------------------------------------------------------
// Note corner colors will be stomped if the base graphic's color changes.
//-----------------------------------------------------------------------------
void CGeometry::SetBottomVerticesColor( color32 c )
{
if ( m_bHorizontalGradient )
{
for ( int i = 0; i < m_VertexColors.Count(); i += 4 )
{
m_VertexColors[i+1] = c;
m_VertexColors[i+2] = c;
}
}
else
{
for ( int i = 0; i < m_VertexColors.Count(); i += 4 )
{
m_VertexColors[i + 2] = c;
m_VertexColors[i + 3] = c;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CGeometry::DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex, color32 extentLineColor )
{
if ( !m_bVisible )
return;
float lineWidth = 2.0;
// Time to invent some render data to draw this thing.
{
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y + lineWidth ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y + lineWidth ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri;
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 1;
tri.m_PointIndex[2] = 2;
renderGeometry.m_Triangles.AddToTail( tri );
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 2;
tri.m_PointIndex[2] = 3;
renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0;
renderGeometry.m_AnimationRate = m_AnimationRate;
renderGeometry.m_bAnimate = false;
renderGeometry.m_AnimStartTime = m_AnimStartTime;
renderGeometry.m_pImageAlias = NULL;
}
{
// Time to invent some render data to draw this thing.
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x - lineWidth, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x - lineWidth, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri;
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 1;
tri.m_PointIndex[2] = 2;
renderGeometry.m_Triangles.AddToTail( tri );
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 2;
tri.m_PointIndex[2] = 3;
renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0;
renderGeometry.m_AnimationRate = m_AnimationRate;
renderGeometry.m_bAnimate = false;
renderGeometry.m_AnimStartTime = m_AnimStartTime;
renderGeometry.m_pImageAlias = NULL;
}
{
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y - lineWidth ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y - lineWidth ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_BottomRight.x, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri;
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 1;
tri.m_PointIndex[2] = 2;
renderGeometry.m_Triangles.AddToTail( tri );
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 2;
tri.m_PointIndex[2] = 3;
renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0;
renderGeometry.m_AnimationRate = m_AnimationRate;
renderGeometry.m_bAnimate = false;
renderGeometry.m_AnimStartTime = m_AnimStartTime;
renderGeometry.m_pImageAlias = NULL;
}
{
// Time to invent some render data to draw this thing.
int i = renderGeometryLists[firstListIndex].AddToTail();
CRenderGeometry &renderGeometry = renderGeometryLists[firstListIndex][i];
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x + lineWidth, m_Extents.m_TopLeft.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 0) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x + lineWidth, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 1 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
renderGeometry.m_Positions.AddToTail( Vector2D( m_Extents.m_TopLeft.x, m_Extents.m_BottomRight.y ) );
renderGeometry.m_TextureCoords.AddToTail( Vector2D( 0 , 1) );
renderGeometry.m_VertexColors.AddToTail( extentLineColor );
// Triangles
CTriangle tri;
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 1;
tri.m_PointIndex[2] = 2;
renderGeometry.m_Triangles.AddToTail( tri );
tri.m_PointIndex[0] = 0;
tri.m_PointIndex[1] = 2;
tri.m_PointIndex[2] = 3;
renderGeometry.m_Triangles.AddToTail( tri );
// Anim Info
renderGeometry.m_SheetSequenceNumber = 0;
renderGeometry.m_AnimationRate = m_AnimationRate;
renderGeometry.m_bAnimate = false;
renderGeometry.m_AnimStartTime = m_AnimStartTime;
renderGeometry.m_pImageAlias = NULL;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CRenderGeometry::GetTriangleCount()
{
return m_Triangles.Count();
}
int CRenderGeometry::GetVertexCount()
{
return m_Positions.Count();
}
DmeTime_t CRenderGeometry::GetAnimStartTime()
{
return m_AnimStartTime;
}
//-----------------------------------------------------------------------------
// Return true if the point x, y lies inside the triangle.
// Triangle points should be supplied in clockwise dir.
//-----------------------------------------------------------------------------
bool PointTriangleHitTest( Vector2D tringleVert0, Vector2D tringleVert1, Vector2D tringleVert2, Vector2D point )
{
// Compute vectors
Vector2D v0 = tringleVert2 - tringleVert0;
Vector2D v1 = tringleVert1 - tringleVert0;
Vector2D v2 = point - tringleVert0;
// Compute dot products
float dot00 = v0.Dot( v0 );
float dot01 = v0.Dot( v1 );
float dot02 = v0.Dot( v2 );
float dot11 = v1.Dot( v1 );
float dot12 = v1.Dot( v2 );
// Compute barycentric coordinates
float invDenom = 1 / (dot00 * dot11 - dot01 * dot01);
float u = (dot11 * dot02 - dot01 * dot12) * invDenom;
float v = (dot00 * dot12 - dot01 * dot02) * invDenom;
// Check if point is in triangle
return ( u > 0 ) && ( v > 0 ) && ( u + v < 1 );
}

View File

@@ -0,0 +1,155 @@
//========= Copyright <20> 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
// $NoKeywords: $
//=============================================================================//
#ifndef UIGEOMETRY_H
#define UIGEOMETRY_H
#ifdef _WIN32
#pragma once
#endif
#include "tier1/utlvector.h"
#include "tier1/timeutils.h"
#include "materialsystem/materialsystemutil.h"
#include "bitmap/psheet.h"
#include "resourcesystem/stronghandle.h"
#include "rendersystem/irenderdevice.h"
struct StageRenderInfo_t;
class CGraphicGroup;
//-----------------------------------------------------------------------------
// Geometry makes an array of triangles by indexing into the point data
//-----------------------------------------------------------------------------
class CTriangle
{
public:
int m_PointIndex[3];
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CRenderGeometry
{
public:
int GetTriangleCount();
int GetVertexCount();
DmeTime_t GetAnimStartTime();
CUtlVector< Vector2D > m_Positions;
CUtlVector< Vector2D > m_TextureCoords;
CUtlVector< color32 > m_VertexColors;
CUtlVector< CTriangle > m_Triangles;
union
{
int m_SheetSequenceNumber;
int m_FontTextureID;
};
float m_AnimationRate;
DmeTime_t m_AnimStartTime;
bool m_bAnimate;
const char *m_pImageAlias;
};
typedef CUtlVector< CRenderGeometry > RenderGeometryList_t;
struct LayerRenderLists_t
{
CUtlVector< RenderGeometryList_t > m_RenderGeometryLists;
int m_LayerType;
IMaterial *m_pMaterial;
CSheet *m_pSheet;
HRenderTextureStrong m_hTexture;
};
struct RectExtents_t
{
Vector2D m_TopLeft;
Vector2D m_BottomRight;
};
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CGeometry
{
public:
CGeometry();
int GetTriangleCount()
{
return m_Triangles.Count();
}
void SetResultantColor( color32 parentColor );
void UpdateRenderTransforms( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup );
void UpdateRenderData( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex );
void GetBounds( Rect_t &bounds );
CUtlVector< Vector2D > m_RelativePositions;
CUtlVector< Vector2D > m_TextureCoords;
CUtlVector< color32 > m_VertexColors;
CUtlVector< CTriangle > m_Triangles;
Vector2D m_Center;
Vector2D m_Scale;
float m_Rotation;
color32 m_Color;
color32 m_TopColor;
color32 m_BottomColor;
bool m_bHorizontalGradient;
int m_SheetSequenceNumber;
float m_AnimationRate;
int m_Sublayer;
bool m_bMaintainAspectRatio;
bool m_bVisible;
DmeTime_t m_AnimStartTime;
bool m_bAnimate;
matrix3x4_t m_RenderToScreen;
matrix3x4_t m_RenderToScreenHoldAspectRatio;
bool m_bDirtyExtents; // if true, recalculate extents on the next render.
RectExtents_t m_Extents;
void CalculateExtents();
void DrawExtents( CUtlVector< RenderGeometryList_t > &renderGeometryLists, int firstListIndex, color32 extentLineColor );
private:
void CalculateExtentsMatrix( const StageRenderInfo_t &stageRenderInfo, const CGraphicGroup *pGroup );
// For applying color gradients
void SetResultantColor( bool bTop, color32 parentColor );
void SetTopVerticesColor( color32 c );
void SetBottomVerticesColor( color32 c );
// Use this matrix to calcuate extents positions on screen.
matrix3x4_t m_ExtentsMatrix;
};
extern bool PointTriangleHitTest( Vector2D tringleVert0, Vector2D tringleVert1, Vector2D tringleVert2, Vector2D point );
#endif // UIGEOMETRY_H