Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

767 lines
24 KiB

//=========== (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 );
}