File: ParticleManager.h

package info (click to toggle)
freespace2 24.2.0%2Brepack-1
  • links: PTS, VCS
  • area: non-free
  • in suites: forky, sid
  • size: 43,716 kB
  • sloc: cpp: 595,001; ansic: 21,741; python: 1,174; sh: 457; makefile: 248; xml: 181
file content (191 lines) | stat: -rw-r--r-- 5,755 bytes parent folder | download
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
#ifndef PARTICLE_MANAGER_H
#define PARTICLE_MANAGER_H
#pragma once

#include "globalincs/pstypes.h"
#include "particle/ParticleEffect.h"
#include "particle/ParticleSource.h"
#include "particle/ParticleSourceWrapper.h"
#include "utils/id.h"

namespace particle {
struct particle_effect_tag {
};
/**
 * The particle index type.
 */
using ParticleEffectHandle = ::util::ID<particle_effect_tag, ptrdiff_t, -1>;

/**
 * @brief Manages high-level particle effects and sources
 *
 * @ingroup particleSystems
 *
 * This class is responsible for managing the loaded effects and processing the created particle sources. The whole effect
 * subsystem is designed to not allocate memory at runtime (except if the vector resizes but that should only happen a few times).
 */
class ParticleManager {
 private:
	SCP_vector<std::shared_ptr<ParticleEffect>> m_effects; //!< All parsed effects

	SCP_vector<ParticleSource> m_sources; //!< The currently active sources

	bool m_processingSources = false; //!< @c true if sources are currently being processed
	/**
	 * If the sources are currently being processed, no additional sources can be added. Instead, they are added to this
	 * vector and then added to the main vector when processing is done.
	 */
	SCP_vector<ParticleSource> m_deferredSourceAdding;

	/**
	 * The global paticle manager
	 */
	static std::unique_ptr<ParticleManager> m_manager;

	/**
	 * @brief Creates a source and returns a pointer to it
	 *
	 * This also handles the case when a source is created when current processing the sources
	 *
	 * @warning The pointer is temporary and only valid until the #m_sources is modified!
	 * @return The source pointer
	 */
	ParticleSource* createSource();
 public:
	ParticleManager() {}

	/**
	 * @brief Initializes the effect system
	 *
	 * This creates the ParticleManager and parses the config files
	 */
	static void init();

	/**
	 * @brief Gets the global particle manager
	 * @return The particle manager
	 */
	static inline ParticleManager* get() {
		Assertion(m_manager != nullptr, "ParticleManager was not properly inited!");

		return m_manager.get();
	}

	/**
	 * @brief Shuts down the particle effect system
	 */
	static void shutdown();

	/**
	 * @brief Gets an effect by index
	 * @param effectID The id of the effect to retrieve
	 * @return The particle effect pointer, will not be @c nullptr
	 */
	inline ParticleEffectPtr getEffect(ParticleEffectHandle effectID)
	{
		Assertion(effectID.value() >= 0 &&
		              effectID.value() < static_cast<ParticleEffectHandle::impl_type>(m_effects.size()),
		          "Particle effect index " PTRDIFF_T_ARG " is invalid!", effectID.value());

		return m_effects[effectID.value()].get();
	}

	/**
	 * @brief Gets an effect by name
	 *
	 * @note If possible, only call this once and then store the index. The lookup is being done by a sequential search
	 * which means it's pretty slow.
	 *
	 * @param name The name of the effect that is being searched, may not be empty
	 * @return The index of the effect
	 */
	ParticleEffectHandle getEffectByName(const SCP_string& name);

	/**
	 * @brief Adds an effect
	 * @param effect The effect to add
	 * @return The index of the added effect
	 */
	ParticleEffectHandle addEffect(ParticleEffectPtr effect);

	/**
	 * @brief Does one processing step of the particle manager
	 * @param frameTime The length of the current frame
	 */
	void doFrame(float frameTime);

	/**
	 * @brief Removes all sources
	 */
	void clearSources();

	/**
	 * @brief Pages in all used effects
	 */
	void pageIn();

	/**
	 * @brief Creates a source for the specified effect
	 *
	 * This returns a wrapper class because some effects may create multiple sources.
	 *
	 * @param index The index of the effect
	 * @return A wrapper class which allows access to the created sources
	 */
	ParticleSourceWrapper createSource(ParticleEffectHandle index);
};

namespace internal {
/**
 * @brief Parses an effect element
 *
 * This can either be the name of an existing effect or a new effect which is created in-place. If forcedType is
 * specified then the effect will have the specified type or an error will be generated.
 *
 * @param forcedType The type the effect should have, EffectType::Invalid can be specified for any effect type
 * @param name The name of the created effect, an empty string means no special name
 * @return The index of the added effect
 */
ParticleEffectHandle parseEffectElement(EffectType forcedType = EffectType::Invalid, const SCP_string& name = "");

/**
 * @brief Utility function for required_string
 *
 * If no_create is @c false then this will act like #required_string, otherwise it will be an #optional_string
 *
 * @param token The token to check for
 * @param no_create The no_create value
 * @return @c true if the token was present, @c false otherwise
 */
bool required_string_if_new(const char* token, bool no_create);

/**
 * @brief Parses an animation or list of animations.
 *
 * Parses an animation or list of animations and returns the handle(s). If critical is @c true then a failure to load the animation will cause
 * an error. Otherwise it will be cause a warning.
 *
 * @param critical @c true if a failure is critical
 * @return The vector of animation handles
 */

SCP_vector<int> parseAnimationList(bool critical = true);
}

namespace util {
/**
 * @brief Parses an effect name
 *
 * This can be used to parse an effect from another part of the engine. This parses an effect name and returns the
 * index. If the name is not valid an error is displayed.
 *
 * @param objectName Can be optionally specified so the error message is a bit more specific
 * @return The index
 */
ParticleEffectHandle parseEffect(const SCP_string& objectName = "");
}
}


#endif // PARTICLE_MANAGER_H