summaryrefslogtreecommitdiff
path: root/Runtime/Filters/Particles/ParticleEmitter.h
blob: 3622fe2dba746634e26b25a1bd14031527bd2271 (plain)
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
#ifndef PARTICLEEMITTER_H
#define PARTICLEEMITTER_H

#include "Runtime/BaseClasses/GameObject.h"
#include "ParticleStruct.h"
#include "Runtime/Utilities/LinkedList.h"


class Rand;

#define GET_SET_DIRTY_MIN(TYPE,PROP_NAME,VAR_NAME,MIN_VAL) void Set##PROP_NAME (TYPE val) { VAR_NAME = std::max(val,MIN_VAL); SetDirty(); } TYPE Get##PROP_NAME () const { return (TYPE)VAR_NAME; }



class ParticleEmitter : public Unity::Component
{
public:
	REGISTER_DERIVED_ABSTRACT_CLASS (ParticleEmitter, Unity::Component)
	DECLARE_OBJECT_SERIALIZE (ParticleEmitter)

	ParticleEmitter (MemLabelId label, ObjectCreationMode mode);
	
	void SetEmit (bool emit);
	bool IsEmitting () const { return m_Emit; }
	
	GET_SET_DIRTY_MIN (float, MinSize, m_MinSize, 0.0f);
	GET_SET_DIRTY_MIN (float, MaxSize, m_MaxSize, 0.0f);
	GET_SET_DIRTY_MIN (float, MinEnergy, m_MinEnergy, 0.0f);
	GET_SET_DIRTY_MIN (float, MaxEnergy, m_MaxEnergy, 0.0f);
	GET_SET_DIRTY_MIN (float, MinEmission, m_MinEmission, 0.0f);
	GET_SET_DIRTY_MIN (float, MaxEmission, m_MaxEmission, 0.0f);

	GET_SET_DIRTY (float, EmitterVelocityScale, m_EmitterVelocityScale);
	GET_SET_DIRTY (Vector3f, WorldVelocity, m_WorldVelocity);
	GET_SET_DIRTY (Vector3f, LocalVelocity, m_LocalVelocity);
	GET_SET_DIRTY (Vector3f, RndVelocity, m_RndVelocity);
	GET_SET_DIRTY (bool, RndRotation, m_RndInitialRotations);
	GET_SET_DIRTY (float, AngularVelocity, m_AngularVelocity);

	float GetRndAngularVelocity () const { return m_RndAngularVelocity; }
	void SetRndAngularVelocity (float val) { if (val < 0) val = 0; m_RndAngularVelocity = val; SetDirty(); }
	
	bool GetUseWorldSpace () const {	return m_UseWorldSpace; }
	void SetUseWorldSpace (bool val) { m_UseWorldSpace = val; } // TODO: set dirty?
	
	// Emit particleCount particles
	void Emit (unsigned int particleCount, float invDeltaTime);
	
	// This is needed, so that subsequent calls to Emit() will each only emit at the current location, and not along the line
	// between the current and last location.
	void EmitResetEmitterPos (int particleCount, float invDeltaTime) { ResetEmitterPos(); Emit (particleCount, invDeltaTime); }

	// Emit one particle
	void Emit (const Vector3f &pos, const Vector3f &dir, float size, float energy, const ColorRGBA32 &color, float rotation, float angularVelocity);
	
	void Deactivate (DeactivateOperation operation);
	void AwakeFromLoad (AwakeFromLoadMode awakeMode);

	// clear all particles.
	void ClearParticles ();
	
	void ReadParticles(  SimpleParticle*__restrict particle, int baseIndex, int count ) const;
	void WriteParticles( const SimpleParticle* __restrict particle, int count );
	
	int GetParticleCount() const { return m_Particles.size(); }
	
	static void UpdateAllParticleSystems();
	void UpdateParticleSystem(float deltaTime);

	const ParticleArray& GetParticles() const { return m_Particles; }
	ParticleArray& GetParticles() { return m_Particles; }
	const PrivateParticleInfo& GetPrivateInfo() const { return m_PrivateInfo; }

	bool GetEnabled () const { return m_Enabled; } 
	void SetEnabled (bool enabled);

	static void InitializeClass ();
	static void CleanupClass ();
	
protected:
	// Sets "does this emitter have to be updated next frame" flags.
	void UpdateManagerState( bool updateParticles );

private:
	// Subclasses have to override this function to place particles
	virtual void SetupParticles (ParticleArray& particles, const Vector3f& velocityOffset,
			const Matrix3x3f& rotation, int firstIndex) = 0;

	// Emit particles
	void TimedEmit (float deltaTime);
	
	void ResetEmitterPos	();
	void CalcOffsets (Vector3f *velocityOffset, Matrix3x3f *localRotation, float invDeltaTime);

protected:
	Vector3f            m_EmitterPos;
	Vector3f            m_PreviousEmitterPos;

protected:
	ParticleArray       m_Particles;
	PrivateParticleInfo m_PrivateInfo;
	float               m_EmissionFrac;

	float		m_MinSize; ///< minimum size range {0, infinity }
	float		m_MaxSize; ///< maximum size range {0, infinity }
	float		m_MinEnergy; ///< minimum energy range { 0, infinity }
	float		m_MaxEnergy; ///< maximum energy	range { 0, infinity }

	float		m_MinEmission; ///< minimum emissions per second range { 0, infinity }
	float		m_MaxEmission; ///< maximum emissions per second range { 0, infinity }

	float		m_EmitterVelocityScale;///< Scales velocity of the emitter 

	Vector3f	m_WorldVelocity;

	Vector3f	m_LocalVelocity;

	Vector3f    m_TangentVelocity;

	Vector3f	m_RndVelocity;		

	bool		m_UseWorldSpace; ///< Are particles simulated in WorldSpace or in LocalSpace?

	bool		m_RndInitialRotations; ///< Should initial particle rotations be randomized?
	float		m_RndAngularVelocity;
	float		m_AngularVelocity;
	
	bool        m_Enabled;
	bool        m_Emit;
	bool        m_OneShot;
	bool        m_FirstFrame;
	
protected:

	void InitParticleEnergy(Rand& r, Particle& p, float dt);
		
	#if DOXYGEN
	///////// @TODO: DO EASIER BACKWARDS COMPATIBILITY: THEN WE DONT NEED THIS CRAP
	float minSize; ///< minimum size range {0, infinity }
	float maxSize; ///< minimum size range {0, infinity }
	float minEnergy; ///< minimum size range {0, infinity }
	float maxEnergy; ///< minimum size range {0, infinity }
	float minEmission; ///< minimum size range {0, infinity }
	float maxEmission; ///< minimum size range {0, infinity }
	#endif

private:
	ListNode<ParticleEmitter> m_EmittersListNode;
};

#endif