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.
556 lines
15 KiB
556 lines
15 KiB
5 years ago
|
//========= Copyright Valve Corporation, All rights reserved. ============//
|
||
|
//
|
||
|
// Purpose: A panel that display particle systems
|
||
|
//
|
||
|
//=============================================================================//
|
||
|
|
||
|
#include "cbase.h"
|
||
|
#include <KeyValues.h>
|
||
|
#include <vgui/IScheme.h>
|
||
|
#include <vgui/ISurface.h>
|
||
|
#include <vgui_controls/EditablePanel.h>
|
||
|
#include "vgui/IVGui.h"
|
||
|
|
||
|
#include "tf_particlepanel.h"
|
||
|
#include "matsys_controls/matsyscontrols.h"
|
||
|
#include "VGuiMatSurface/IMatSystemSurface.h"
|
||
|
#include "tier2/renderutils.h"
|
||
|
#include "renderparm.h"
|
||
|
|
||
|
using namespace vgui;
|
||
|
|
||
|
|
||
|
CTFParticlePanel::ParticleEffect_t::ParticleEffect_t()
|
||
|
: m_bLoop( true )
|
||
|
, m_pParticleSystem( NULL )
|
||
|
, m_flLastTime( FLT_MAX )
|
||
|
, m_ParticleSystemName( NULL )
|
||
|
, m_bStartActivated( true )
|
||
|
, m_flScale( 1.f )
|
||
|
, m_flEndTime( FLT_MAX )
|
||
|
, m_nXPos( 0 )
|
||
|
, m_nYPos( 0 )
|
||
|
, m_Angles( 0.f, 0.f, 0.f )
|
||
|
, m_pParent( NULL )
|
||
|
, m_bForceStopped( false )
|
||
|
, m_bAutoDelete( false )
|
||
|
, m_bStarted( false )
|
||
|
{}
|
||
|
|
||
|
|
||
|
DECLARE_BUILD_FACTORY( CTFParticlePanel );
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Constructor, destructor
|
||
|
//-----------------------------------------------------------------------------
|
||
|
CTFParticlePanel::CTFParticlePanel( vgui::Panel *pParent, const char *pName )
|
||
|
: BaseClass( pParent, pName )
|
||
|
{
|
||
|
m_Camera.m_flZNear = 3.0f;
|
||
|
m_Camera.m_flZFar = 16384.0f * 1.73205080757f;
|
||
|
m_Camera.m_flFOV = 30.0f;
|
||
|
m_Camera.m_origin = Vector(0,0,0);
|
||
|
m_Camera.m_angles = QAngle(0,0,0);
|
||
|
|
||
|
m_pLightmapTexture.Init( "//platform/materials/debug/defaultlightmap", "editor" );
|
||
|
m_DefaultEnvCubemap.Init( "editor/cubemap", "editor", true );
|
||
|
}
|
||
|
|
||
|
CTFParticlePanel::~CTFParticlePanel()
|
||
|
{
|
||
|
m_pLightmapTexture.Shutdown();
|
||
|
m_DefaultEnvCubemap.Shutdown();
|
||
|
m_vecParticleEffects.PurgeAndDeleteElements();
|
||
|
}
|
||
|
|
||
|
|
||
|
void CTFParticlePanel::ApplySettings( KeyValues *inResourceData )
|
||
|
{
|
||
|
BaseClass::ApplySettings( inResourceData );
|
||
|
|
||
|
KeyValues *pKVParticleEffects = inResourceData->FindKey( "ParticleEffects" );
|
||
|
if ( pKVParticleEffects )
|
||
|
{
|
||
|
FOR_EACH_SUBKEY( pKVParticleEffects, pKVEffect )
|
||
|
{
|
||
|
m_vecParticleEffects[ m_vecParticleEffects.AddToTail() ] = new ParticleEffect_t();
|
||
|
ParticleEffect_t* pEffect = m_vecParticleEffects.Tail();
|
||
|
|
||
|
// get the position
|
||
|
int alignScreenWide = GetWide(), alignScreenTall = GetTall(); // screen dimensions used for pinning in splitscreen
|
||
|
|
||
|
int x, y;
|
||
|
GetPos(x, y);
|
||
|
const char *xstr = pKVEffect->GetString( "particle_xpos", NULL );
|
||
|
const char *ystr = pKVEffect->GetString( "particle_ypos", NULL );
|
||
|
|
||
|
if (xstr)
|
||
|
{
|
||
|
bool bRightAlign = false;
|
||
|
bool bCenterAlign = false;
|
||
|
// look for alignment flags
|
||
|
if (xstr[0] == 'r' || xstr[0] == 'R')
|
||
|
{
|
||
|
bRightAlign = true;
|
||
|
xstr++;
|
||
|
}
|
||
|
else if (xstr[0] == 'c' || xstr[0] == 'C')
|
||
|
{
|
||
|
bCenterAlign = true;
|
||
|
xstr++;
|
||
|
}
|
||
|
|
||
|
// get the value
|
||
|
x = atoi(xstr);
|
||
|
// scale the x up to our screen co-ords
|
||
|
if ( IsProportional() )
|
||
|
{
|
||
|
x = scheme()->GetProportionalScaledValueEx(GetScheme(), x);
|
||
|
}
|
||
|
// now correct the alignment
|
||
|
if ( bRightAlign )
|
||
|
{
|
||
|
x = alignScreenWide - x;
|
||
|
}
|
||
|
else if ( bCenterAlign )
|
||
|
{
|
||
|
x = (alignScreenWide / 2) + x;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (ystr)
|
||
|
{
|
||
|
bool bBottomAlign = false;
|
||
|
bool bCenterAlign = false;
|
||
|
// look for alignment flags
|
||
|
if (ystr[0] == 'r' || ystr[0] == 'R')
|
||
|
{
|
||
|
bBottomAlign = true;
|
||
|
ystr++;
|
||
|
}
|
||
|
else if (ystr[0] == 'c' || ystr[0] == 'C')
|
||
|
{
|
||
|
bCenterAlign = true;
|
||
|
ystr++;
|
||
|
}
|
||
|
y = atoi(ystr);
|
||
|
if (IsProportional())
|
||
|
{
|
||
|
// scale the y up to our screen co-ords
|
||
|
y = scheme()->GetProportionalScaledValueEx(GetScheme(), y);
|
||
|
}
|
||
|
// now correct the alignment
|
||
|
if ( bBottomAlign )
|
||
|
{
|
||
|
y = alignScreenTall - y;
|
||
|
}
|
||
|
else if ( bCenterAlign )
|
||
|
{
|
||
|
y = (alignScreenTall / 2) + y;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pEffect->m_nXPos = x;
|
||
|
pEffect->m_nYPos = y;
|
||
|
|
||
|
pEffect->m_flScale = pKVEffect->GetFloat( "particle_scale", 1.f );
|
||
|
// Scale the scale factor the same way we do the XY position coordinates
|
||
|
if( IsProportional() )
|
||
|
{
|
||
|
int wide, tall;
|
||
|
surface()->GetScreenSize( wide, tall );
|
||
|
|
||
|
int proH, proW;
|
||
|
surface()->GetProportionalBase( proW, proH );
|
||
|
double scale = (double)tall / (double)proH;
|
||
|
pEffect->m_flScale *= scale;
|
||
|
}
|
||
|
|
||
|
pEffect->m_pParent = this;
|
||
|
pEffect->m_bLoop = pKVEffect->GetBool( "loop", true );
|
||
|
pEffect->m_bStartActivated = pKVEffect->GetBool( "start_activated", true );
|
||
|
pEffect->SetParticleSystem( pKVEffect->GetString( "particleName" ) );
|
||
|
|
||
|
// Read angles for the particle system
|
||
|
{
|
||
|
float x1,y1,z1;
|
||
|
const char* pszAngles = pKVEffect->GetString( "angles" );
|
||
|
if( *pszAngles )
|
||
|
{
|
||
|
if( pEffect->m_pParticleSystem && sscanf( pszAngles, "%f %f %f", &x1, &y1, &z1 ) == 3 )
|
||
|
{
|
||
|
pEffect->m_Angles = QAngle( x1, y1, z1 );
|
||
|
Quaternion q;
|
||
|
AngleQuaternion( pEffect->m_Angles , q );
|
||
|
pEffect->m_pParticleSystem->SetControlPointOrientation( 0, q );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
pEffect->SetControlPointValue( 0, Vector(0,0,0) );
|
||
|
// Read all control point values
|
||
|
const char* pszControlPoint = NULL;
|
||
|
int nControlPointNumber = 0;
|
||
|
do
|
||
|
{
|
||
|
pszControlPoint = pKVEffect->GetString( VarArgs("control_point%d", nControlPointNumber), "" );
|
||
|
if ( *pszControlPoint )
|
||
|
{
|
||
|
float x2,y2,z2;
|
||
|
if (sscanf(pszControlPoint, "%f %f %f", &x2, &y2, &z2 ) == 3)
|
||
|
{
|
||
|
pEffect->SetControlPointValue( nControlPointNumber, Vector( x2, y2, z2 ) );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
++nControlPointNumber;
|
||
|
}
|
||
|
while( *pszControlPoint );
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Scheme
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFParticlePanel::ApplySchemeSettings( vgui::IScheme *pScheme )
|
||
|
{
|
||
|
BaseClass::ApplySchemeSettings( pScheme );
|
||
|
|
||
|
SetMouseInputEnabled( false );
|
||
|
SetKeyBoardInputEnabled( false );
|
||
|
}
|
||
|
|
||
|
void CTFParticlePanel::OnCommand( const char *command )
|
||
|
{
|
||
|
if ( !Q_strnicmp( command, "start", ARRAYSIZE("start") - 1 ) )
|
||
|
{
|
||
|
// Check if they specified a particular one to turn on
|
||
|
const char* pszNum = command + ARRAYSIZE( "start" ) - 1;
|
||
|
int nIndex = m_vecParticleEffects.InvalidIndex();
|
||
|
|
||
|
if( pszNum && pszNum[0] )
|
||
|
{
|
||
|
nIndex = atoi(pszNum);
|
||
|
Assert( nIndex >= 0 && nIndex < m_vecParticleEffects.Count() );
|
||
|
}
|
||
|
|
||
|
FOR_EACH_VEC( m_vecParticleEffects, i )
|
||
|
{
|
||
|
if ( nIndex != m_vecParticleEffects.InvalidIndex() && i != nIndex )
|
||
|
continue;
|
||
|
|
||
|
ParticleEffect_t* pEffect = m_vecParticleEffects[ i ];
|
||
|
|
||
|
if( !pEffect->m_pParticleSystem )
|
||
|
{
|
||
|
pEffect->SetParticleSystem( pEffect->m_ParticleSystemName );
|
||
|
}
|
||
|
|
||
|
if( !pEffect->m_pParticleSystem )
|
||
|
continue;
|
||
|
|
||
|
pEffect->StartupParticleCollection();
|
||
|
pEffect->m_pParticleSystem->StartEmission();
|
||
|
pEffect->m_bForceStopped = false;
|
||
|
}
|
||
|
}
|
||
|
else if ( !Q_strnicmp( command, "stop", ARRAYSIZE("stop") - 1 ) )
|
||
|
{
|
||
|
// Check if they specified a specific one to turn off
|
||
|
const char* pszNum = command + ARRAYSIZE( "start" ) - 1;
|
||
|
if( pszNum && pszNum[0] )
|
||
|
{
|
||
|
int iIndex = atoi(pszNum);
|
||
|
Assert( iIndex >= 0 && iIndex < m_vecParticleEffects.Count() );
|
||
|
|
||
|
ParticleEffect_t* pEffect = m_vecParticleEffects[iIndex];
|
||
|
if( pEffect->m_pParticleSystem )
|
||
|
{
|
||
|
pEffect->m_pParticleSystem->StopEmission();
|
||
|
pEffect->m_bForceStopped = true;
|
||
|
}
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
// Turn them ALL off
|
||
|
FOR_EACH_VEC( m_vecParticleEffects, i )
|
||
|
{
|
||
|
ParticleEffect_t* pEffect = m_vecParticleEffects[ i ];
|
||
|
if( pEffect->m_pParticleSystem )
|
||
|
{
|
||
|
pEffect->m_pParticleSystem->StopEmission();
|
||
|
pEffect->m_bForceStopped = true;
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void CTFParticlePanel::FireParticleEffect( const char *pszName, int xPos, int yPos, float flScale, bool bLoop, float flEndTime )
|
||
|
{
|
||
|
m_vecParticleEffects[ m_vecParticleEffects.AddToTail() ] = new ParticleEffect_t();
|
||
|
ParticleEffect_t* pEffect = m_vecParticleEffects.Tail();
|
||
|
|
||
|
int iParentAbsX, iParentAbsY;
|
||
|
vgui::ipanel()->GetAbsPos( GetParent()->GetVPanel(), iParentAbsX, iParentAbsY );
|
||
|
|
||
|
pEffect->m_pParent = this;
|
||
|
pEffect->m_nXPos = xPos - iParentAbsX;
|
||
|
pEffect->m_nYPos = yPos - iParentAbsY;
|
||
|
pEffect->m_flScale = flScale;
|
||
|
pEffect->m_bLoop = bLoop;
|
||
|
pEffect->m_bAutoDelete = true; // This will get automatically deleted once it stops
|
||
|
pEffect->m_bStartActivated = true;
|
||
|
pEffect->m_flEndTime = gpGlobals->curtime + flEndTime;
|
||
|
|
||
|
if( IsProportional() )
|
||
|
{
|
||
|
int wide, tall;
|
||
|
surface()->GetScreenSize( wide, tall );
|
||
|
|
||
|
int proH, proW;
|
||
|
surface()->GetProportionalBase( proW, proH );
|
||
|
double scale = (double)tall / (double)proH;
|
||
|
pEffect->m_flScale *= scale;
|
||
|
}
|
||
|
|
||
|
for ( int i = 0; i < MAX_PARTICLE_CONTROL_POINTS; ++i )
|
||
|
{
|
||
|
pEffect->SetControlPointValue( i, Vector( 0, 0, 10.0f * i ) );
|
||
|
}
|
||
|
pEffect->SetParticleSystem( pszName );
|
||
|
}
|
||
|
|
||
|
|
||
|
static bool IsValidHierarchy( CParticleCollection *pCollection )
|
||
|
{
|
||
|
if ( !pCollection->IsValid() )
|
||
|
return false;
|
||
|
|
||
|
for( CParticleCollection *pChild = pCollection->m_Children.m_pHead; pChild; pChild = pChild->m_pNext )
|
||
|
{
|
||
|
if ( !IsValidHierarchy( pChild ) )
|
||
|
return false;
|
||
|
}
|
||
|
return true;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Simulate the particle system
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFParticlePanel::OnTick()
|
||
|
{
|
||
|
BaseClass::OnTick();
|
||
|
|
||
|
float flTime = engine->Time();
|
||
|
|
||
|
bool bAnyActive = false;
|
||
|
// Update all particles
|
||
|
FOR_EACH_VEC_BACK( m_vecParticleEffects, i )
|
||
|
{
|
||
|
bAnyActive |= m_vecParticleEffects[i]->Update( flTime );
|
||
|
// If this effect is done and should auto-delete, then now is when we delete
|
||
|
if( m_vecParticleEffects[i]->m_pParticleSystem == NULL && m_vecParticleEffects[i]->m_bAutoDelete )
|
||
|
{
|
||
|
delete m_vecParticleEffects[i];
|
||
|
m_vecParticleEffects.FastRemove( i );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if ( !bAnyActive )
|
||
|
{
|
||
|
vgui::ivgui()->RemoveTickSignal( GetVPanel() );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CTFParticlePanel::Paint()
|
||
|
{
|
||
|
// This needs calling to reset various counters.
|
||
|
g_pParticleSystemMgr->SetLastSimulationTime( gpGlobals->curtime );
|
||
|
|
||
|
// No particles? Do nothing.
|
||
|
if( m_vecParticleEffects.Count() == 0 )
|
||
|
return;
|
||
|
|
||
|
int screenW, screenH;
|
||
|
vgui::surface()->GetScreenSize( screenW, screenH );
|
||
|
|
||
|
vgui::MatSystemSurface()->Begin3DPaint( 0, 0, screenW, screenH, false );
|
||
|
|
||
|
VMatrix view, projection;
|
||
|
ComputeViewMatrix( &view, m_Camera );
|
||
|
ComputeProjectionMatrix( &projection, m_Camera, screenW, screenH );
|
||
|
|
||
|
CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
|
||
|
|
||
|
pRenderContext->CullMode( MATERIAL_CULLMODE_CCW );
|
||
|
pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, false );
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
||
|
pRenderContext->LoadIdentity( );
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_VIEW );
|
||
|
pRenderContext->LoadMatrix( view );
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||
|
pRenderContext->LoadMatrix( projection );
|
||
|
|
||
|
int iXOffset, iYOffset;
|
||
|
vgui::ipanel()->GetAbsPos( GetVPanel(), iXOffset, iYOffset );
|
||
|
if ( iXOffset > 0 )
|
||
|
iXOffset = 0;
|
||
|
if ( iYOffset > 0 )
|
||
|
iYOffset = 0;
|
||
|
|
||
|
float flXScale = 1.f;
|
||
|
if ( GetWide() > screenW )
|
||
|
flXScale = (float)screenW / GetWide();
|
||
|
float flYScale = 1.f;
|
||
|
if ( GetTall() > screenH )
|
||
|
flYScale = (float)screenH / GetTall();
|
||
|
|
||
|
FOR_EACH_VEC( m_vecParticleEffects, i )
|
||
|
{
|
||
|
m_vecParticleEffects[i]->Paint( pRenderContext, iXOffset, iYOffset, flXScale, flYScale, screenW, screenH );
|
||
|
}
|
||
|
|
||
|
pRenderContext->CullMode( MATERIAL_CULLMODE_CW );
|
||
|
|
||
|
vgui::MatSystemSurface()->End3DPaint();
|
||
|
}
|
||
|
|
||
|
bool CTFParticlePanel::ParticleEffect_t::Update( float flTime )
|
||
|
{
|
||
|
if ( !m_pParticleSystem || !m_bStarted )
|
||
|
return false;
|
||
|
|
||
|
if ( m_flLastTime == FLT_MAX )
|
||
|
{
|
||
|
m_flLastTime = flTime;
|
||
|
}
|
||
|
|
||
|
float flDt = flTime - m_flLastTime;
|
||
|
m_flLastTime = flTime;
|
||
|
|
||
|
Quaternion q;
|
||
|
AngleQuaternion( m_Angles, q );
|
||
|
|
||
|
for ( int i = 0; i < MAX_PARTICLE_CONTROL_POINTS; ++i )
|
||
|
{
|
||
|
if ( !m_pParticleSystem->ReadsControlPoint( i ) )
|
||
|
continue;
|
||
|
|
||
|
m_pParticleSystem->SetControlPoint( i, m_pControlPointValue[i] );
|
||
|
m_pParticleSystem->SetControlPointOrientation( i, q );
|
||
|
m_pParticleSystem->SetControlPointParent( i, i );
|
||
|
}
|
||
|
|
||
|
// Restart the particle system if it's finished
|
||
|
bool bIsInvalid = !IsValidHierarchy( m_pParticleSystem );
|
||
|
|
||
|
if ( !bIsInvalid )
|
||
|
{
|
||
|
m_pParticleSystem->Simulate( flDt, false );
|
||
|
}
|
||
|
|
||
|
// Past our end time?
|
||
|
bool bEnd = gpGlobals->curtime >= m_flEndTime;
|
||
|
|
||
|
if ( m_pParticleSystem->IsFinished() || bIsInvalid || bEnd )
|
||
|
{
|
||
|
delete m_pParticleSystem;
|
||
|
m_pParticleSystem = NULL;
|
||
|
|
||
|
// Loop if we're supposed to
|
||
|
if ( m_bLoop && m_ParticleSystemName.Length() && !m_bForceStopped )
|
||
|
{
|
||
|
m_pParticleSystem = g_pParticleSystemMgr->CreateParticleCollection( m_ParticleSystemName );
|
||
|
}
|
||
|
|
||
|
if ( bIsInvalid && m_pParent )
|
||
|
{
|
||
|
m_pParent->PostActionSignal( new KeyValues( "ParticleSystemReconstructed" ) );
|
||
|
}
|
||
|
m_flLastTime = FLT_MAX;
|
||
|
}
|
||
|
|
||
|
return m_pParticleSystem != NULL;
|
||
|
}
|
||
|
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Startup, shutdown particle collection
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFParticlePanel::ParticleEffect_t::StartupParticleCollection()
|
||
|
{
|
||
|
if ( m_pParticleSystem && m_pParent )
|
||
|
{
|
||
|
vgui::ivgui()->AddTickSignal( m_pParent->GetVPanel(), 0 );
|
||
|
}
|
||
|
m_flLastTime = FLT_MAX;
|
||
|
m_bStarted = true;
|
||
|
}
|
||
|
|
||
|
void CTFParticlePanel::ParticleEffect_t::ShutdownParticleCollection()
|
||
|
{
|
||
|
if ( m_pParticleSystem && m_pParent )
|
||
|
{
|
||
|
delete m_pParticleSystem;
|
||
|
m_pParticleSystem = NULL;
|
||
|
}
|
||
|
m_bStarted = false;
|
||
|
}
|
||
|
|
||
|
//-----------------------------------------------------------------------------
|
||
|
// Set the particle system to draw
|
||
|
//-----------------------------------------------------------------------------
|
||
|
void CTFParticlePanel::ParticleEffect_t::SetParticleSystem( const char* pszParticleSystemName )
|
||
|
{
|
||
|
ShutdownParticleCollection();
|
||
|
|
||
|
if( !g_pParticleSystemMgr->IsParticleSystemDefined( pszParticleSystemName ) )
|
||
|
{
|
||
|
AssertMsg1( false, "%s is not a valid particle system name", pszParticleSystemName );
|
||
|
return;
|
||
|
}
|
||
|
m_pParticleSystem = g_pParticleSystemMgr->CreateParticleCollection( pszParticleSystemName );
|
||
|
m_ParticleSystemName = pszParticleSystemName;
|
||
|
|
||
|
m_pParent->PostActionSignal( new KeyValues( "ParticleSystemReconstructed" ) );
|
||
|
|
||
|
if( m_bStartActivated )
|
||
|
{
|
||
|
StartupParticleCollection();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
void CTFParticlePanel::ParticleEffect_t::Paint( CMatRenderContextPtr& pRenderContext, int iXOffset, int iYOffset, float flXScale, float flYScale, int screenW, int screenH )
|
||
|
{
|
||
|
if ( !m_pParticleSystem || !m_bStarted )
|
||
|
return;
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||
|
pRenderContext->PushMatrix();
|
||
|
pRenderContext->LoadIdentity();
|
||
|
|
||
|
pRenderContext->Ortho( 0, 0, screenW, screenH, -9999, 9999 );
|
||
|
|
||
|
pRenderContext->Translate( flXScale * ( m_nXPos + iXOffset ), screenH - flYScale * ( m_nYPos + iYOffset ), 0.f );
|
||
|
pRenderContext->Scale( m_flScale, m_flScale, m_flScale );
|
||
|
|
||
|
// Render Particles
|
||
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
||
|
pRenderContext->PushMatrix();
|
||
|
pRenderContext->LoadIdentity( );
|
||
|
|
||
|
m_pParticleSystem->Render( pRenderContext );
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_MODEL );
|
||
|
pRenderContext->PopMatrix();
|
||
|
|
||
|
pRenderContext->MatrixMode( MATERIAL_PROJECTION );
|
||
|
pRenderContext->PopMatrix();
|
||
|
}
|