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