aboutsummaryrefslogtreecommitdiff
path: root/sp/src/game/client/particles_simple.h
blob: 4b30f110ea5da544154166422b906007ba9c55bb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//===========================================================================//

#ifndef PARTICLES_SIMPLE_H
#define PARTICLES_SIMPLE_H
#ifdef _WIN32
#pragma once
#endif

#include "particlemgr.h"
#include "particlesphererenderer.h"
#include "smartptr.h"


// ------------------------------------------------------------------------------------------------ //
// CParticleEffect is the base class that you can derive from to make a particle effect.
// These can be used two ways:
//
// 1. Allocate a CParticleEffect-based object using the class's static Create() function. This gives
//    you back a smart pointer that handles the reference counting for you.
//
// 2. Contain a CParticleEffect object in your class.
// ------------------------------------------------------------------------------------------------ //

class CParticleEffect : public IParticleEffect
{
public:
	DECLARE_CLASS_NOBASE( CParticleEffect );

	friend class CRefCountAccessor;

	// Call this before adding a bunch of particles to give it a rough estimate of where
	// your particles are for sorting amongst other translucent entities.
	void				SetSortOrigin( const Vector &vSortOrigin );

	PMaterialHandle		GetPMaterial(const char *name);
	
	Particle*			AddParticle( unsigned int particleSize, PMaterialHandle material, const Vector &origin );

	CParticleEffectBinding&	GetBinding()	{ return m_ParticleEffect; }

	const char *GetEffectName();

	void AddFlags( int iFlags ) { m_Flags |= iFlags; }
	void RemoveFlags( int iFlags ) { m_Flags &= ~iFlags; }

	void SetDontRemove( bool bSet )
	{
		if( bSet )
			AddFlags( FLAG_DONT_REMOVE );
		else
			RemoveFlags( FLAG_DONT_REMOVE );
	}

// IParticleEffect overrides
public:

	virtual void				SetParticleCullRadius( float radius );
	virtual void				NotifyRemove( void );
	virtual const Vector &		GetSortOrigin();
	virtual void				NotifyDestroyParticle( Particle* pParticle );
	virtual void				Update( float flTimeDelta );

	// All Create() functions should call this so the effect deletes itself
	// when it is removed from the particle manager.
	void						SetDynamicallyAllocated( bool bDynamic=true );

	virtual bool				ShouldSimulate() const { return m_bSimulate; }
	virtual void				SetShouldSimulate( bool bSim ) { m_bSimulate = bSim; }

	int							AllocateToolParticleEffectId();
	int							GetToolParticleEffectId() const;
protected:
								CParticleEffect( const char *pDebugName );
	virtual						~CParticleEffect();

	// Returns nonzero if Release() has been called.
	int							IsReleased();
	
	enum
	{
		FLAG_ALLOCATED = (1<<1),	// Most of the CParticleEffects are dynamically allocated but
								// some are member variables of a class. If they're member variables.
		FLAG_DONT_REMOVE = (1<<2),
	};

	// Used to track down bugs.
	char const					*m_pDebugName;

	CParticleEffectBinding		m_ParticleEffect;
	Vector						m_vSortOrigin;
	
	int							m_Flags;		// Combination of CParticleEffect::FLAG_

	bool						m_bSimulate;
	int							m_nToolParticleEffectId;

private:
	// Update the reference count.
	void						AddRef();
	void						Release();
	
	int							m_RefCount;		// When this goes to zero and the effect has no more active
												// particles, (and it's dynamically allocated), it will delete itself.

	CParticleEffect( const CParticleEffect & ); // not defined, not accessible
};

inline int CParticleEffect::GetToolParticleEffectId() const
{
	return m_nToolParticleEffectId;
}

inline int CParticleEffect::AllocateToolParticleEffectId()
{
	m_nToolParticleEffectId = ParticleMgr()->AllocateToolParticleEffectId();
	return m_nToolParticleEffectId;
}


//-----------------------------------------------------------------------------
// Particle flags
//-----------------------------------------------------------------------------
enum SimpleParticleFlag_t
{
	SIMPLE_PARTICLE_FLAG_WINDBLOWN = 0x1,
	SIMPLE_PARTICLE_FLAG_NO_VEL_DECAY = 0x2	// Used by the blood spray emitter. By default, it decays the
											// particle velocity.
};

class SimpleParticle : public Particle
{
public:
	SimpleParticle() : m_iFlags(0) {}

	// AddSimpleParticle automatically initializes these fields.
	Vector		m_vecVelocity;
	float		m_flRoll;
	float		m_flDieTime;	// How long it lives for.
	float		m_flLifetime;	// How long it has been alive for so far.
	unsigned char	m_uchColor[3];
	unsigned char	m_uchStartAlpha;
	unsigned char	m_uchEndAlpha;
	unsigned char	m_uchStartSize;
	unsigned char	m_uchEndSize;
	unsigned char 	m_iFlags;	// See SimpleParticleFlag_t above
	float		m_flRollDelta;
};



// CSimpleEmitter implements a common way to simulate and render particles.
//
// Effects can add particles to the particle manager and point at CSimpleEmitter
// for the effect so they don't have to implement the simulation code. It simulates
// velocity, and fades their alpha from invisible to solid and back to invisible over their lifetime.
//
// Particles you add using this effect must use the class CParticleSimple::Particle.
class CSimpleEmitter : public CParticleEffect
{
// IParticleEffect overrides.
public:

	DECLARE_CLASS( CSimpleEmitter, CParticleEffect );

	static CSmartPtr<CSimpleEmitter>	Create( const char *pDebugName );

	virtual void	SimulateParticles( CParticleSimulateIterator *pIterator );
	virtual void	RenderParticles( CParticleRenderIterator *pIterator );

	void			SetNearClip( float nearClipMin, float nearClipMax );

	void			SetDrawBeforeViewModel( bool state = true );

	SimpleParticle*	AddSimpleParticle( PMaterialHandle hMaterial, const Vector &vOrigin, float flDieTime=3, unsigned char uchSize=10 );
	
// Overridables for variants like CEmberEffect.
protected:
					CSimpleEmitter( const char *pDebugName = NULL );
	virtual			~CSimpleEmitter();

	virtual	float	UpdateAlpha( const SimpleParticle *pParticle );
	virtual float	UpdateScale( const SimpleParticle *pParticle );
	virtual	float	UpdateRoll( SimpleParticle *pParticle, float timeDelta );
	virtual	void	UpdateVelocity( SimpleParticle *pParticle, float timeDelta );
	virtual Vector	UpdateColor( const SimpleParticle *pParticle );

	float			m_flNearClipMin;
	float			m_flNearClipMax;

private:
	CSimpleEmitter( const CSimpleEmitter & ); // not defined, not accessible
};

//==================================================
// EmberEffect
//==================================================

class CEmberEffect : public CSimpleEmitter
{
public:
							CEmberEffect( const char *pDebugName );
	static CSmartPtr<CEmberEffect>	Create( const char *pDebugName );

	virtual void UpdateVelocity( SimpleParticle *pParticle, float timeDelta );
	virtual Vector UpdateColor( const SimpleParticle *pParticle );

private:
	CEmberEffect( const CEmberEffect & ); // not defined, not accessible
};


//==================================================
// FireSmokeEffect
//==================================================

class CFireSmokeEffect : public CSimpleEmitter
{
public:
								CFireSmokeEffect( const char *pDebugName );
	static CSmartPtr<CFireSmokeEffect>	Create( const char *pDebugName );

	virtual void UpdateVelocity( SimpleParticle *pParticle, float timeDelta );
	virtual float UpdateAlpha( const SimpleParticle *pParticle );

protected:
	VPlane	m_planeClip;

private:
	CFireSmokeEffect( const CFireSmokeEffect & ); // not defined, not accessible
};


//==================================================
// CFireParticle
//==================================================

class CFireParticle : public CSimpleEmitter
{
public:
							CFireParticle( const char *pDebugName );
	static CSmartPtr<CFireParticle>	Create( const char *pDebugName );
	
	virtual Vector UpdateColor( const SimpleParticle *pParticle );

private:
	CFireParticle( const CFireParticle & ); // not defined, not accessible
};


#endif // PARTICLES_SIMPLE_H