Merge branch '138-toggle-free-look-with-hotkey' into main/gingo-test
[ryzomcore.git] / ryzom / client / src / timed_fx_manager.h
bloba4507c6c1ee405d5d56aab58a0cc6ac49cdab2db
1 // Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
19 #ifndef CL_TIMED_FX_MANAGER_H
20 #define CL_TIMED_FX_MANAGER_H
22 #include "nel/misc/vector.h"
23 #include "nel/misc/noise_value.h"
24 #include "game_share/season.h"
25 #include "time_client.h"
26 #include "fx_manager.h"
28 class CSeasonFXSheet;
30 namespace NL3D
32 class UParticleSystemInstance;
33 class UScene;
36 /** A fx that must be spawn at a given season and hour
37 * \author Nicolas Vizerie
38 * \author Nevrax France
39 * \date 2003
41 class CTimedFX
43 public:
44 NLMISC::CVector SpawnPosition;
45 NLMISC::CQuat Rot;
46 NLMISC::CVector Scale;
47 const CSeasonFXSheet *FXSheet;
48 #if !FINAL_VERSION
49 bool FromIG; // true if the fx comes from an ig, or false if it was generated dynamically
50 #endif
51 public:
52 CTimedFX() : SpawnPosition(0.f, 0.f, 0.f), FXSheet(NULL)
54 #if !FINAL_VERSION
55 FromIG = true;
56 #endif
58 NLMISC::CMatrix getInstanceMatrix() const;
61 typedef std::vector<CTimedFX> TTimedFXGroup;
63 /** Manager to spawn fxs at a given season and hour.
64 * \author Nicolas Vizerie
65 * \author Nevrax France
66 * \date 2003
68 class CTimedFXManager
70 private:
71 class CManagedFX;
72 struct CTimeStampedFX
74 CClientDate Date; // the date at which the FX must be added / removed
75 //sint32 DebugDay;
76 CManagedFX *FX; // managed FX
77 bool operator < (const CTimeStampedFX &rhs) const
79 if (Date == rhs.Date) return FX < rhs.FX;
80 else return Date < rhs.Date;
81 } // we want to deal with early dates sooner
82 bool operator == (const CTimeStampedFX &rhs) const { return Date == rhs.Date && FX == rhs.FX; }
83 CTimeStampedFX() : FX(NULL) {}
85 typedef std::set<CTimeStampedFX> TTimeStampedFXPtrSet;
86 struct CManagedFXGroup;
87 struct CCandidateFXListHead;
88 /** A managed FX. Unless it is flagged as 'always intanciated', or is in a group that is shutting down,
89 * such a fx can only be in one set : _FXToAdd if it is not currently instanciated (or is shutting down), and _FXToRemove if it is instanciated and is not being shut down.
90 * and will be removed in the future.
92 class CManagedFX : public CTimedFX
94 public:
95 enum TState { Unknown = 0, Permanent, InAddList, InRemoveList };
96 #ifdef NL_DEBUG
97 CManagedFXGroup *OwnerGroup;
98 #endif
99 NL3D::UParticleSystemInstance Instance; // Pointer to the actual FX. NULL if failed to instanciate or if not instanciated
100 TState State;
101 TTimeStampedFXPtrSet::iterator SetHandle; // if the fx is in a list (see its state), then it is an iterator into that list (for removal)
103 CManagedFX **_PrevCandidateFX; // if the fx has asked to be instanciated, it is inserted in a list of candidate fxs. points the previous "Next" pointer
104 // even if the fx is currently instanciated, it remains in that list (those are the potnetially instanciated fxs)
105 CManagedFX *_NextCandidateFX; // next candidate FX
107 CManagedFX **_PrevInstanciatedFX; // link into instanciated fx list, prev (is also a candidate)
108 CManagedFX *_NextInstanciatedFX; // link into instanciated fx list, next
109 // Tmp for debug
110 #ifdef NL_DEBUG
111 uint32 Magic;
112 #endif
113 public:
114 // ctor
115 CManagedFX()
117 Instance = NULL;
118 State = Unknown;
119 #ifdef NL_DEBUG
120 OwnerGroup = NULL;
121 Magic = 0xbaadcafe;
122 #endif
123 _PrevCandidateFX = NULL;
124 _NextCandidateFX = NULL;
126 _PrevInstanciatedFX = NULL;
127 _NextInstanciatedFX = NULL;
129 // compute start hour of that fx for the given day
130 void computeStartHour(sint32 cycle, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv) const;
131 // compute end hour of that fx for the given day
132 void computeEndHour(sint32 cycle, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv) const;
133 // unlink from list of candidate fxs
134 void unlinkFromCandidateFXList();
135 // unlink from list of instanciated fx. NB : this doesn't remove the model!
136 void unlinkFromInstanciatedFXList();
137 /** Shutdown the fx
139 void shutDown(NL3D::UScene *scene, CFXManager &fxManager);
140 private:
141 void computeHour(sint32 cycle, float bias, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv, float minHour, float maxHour) const;
143 // A group of managed fx. We never resize these vectors after creation so we can keep pointers in them.
144 typedef std::vector<CManagedFX> TManagedFXGroup;
145 struct CManagedFXGroup
147 TManagedFXGroup Group;
148 #ifdef NL_DEBUG
149 EGSPD::CSeason::TSeason Season;
150 #endif
152 // a list of group of managed fxs.
153 typedef std::list<CManagedFXGroup> TManagedFXGroupList;
156 public:
157 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
158 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
159 //\name USER INTERFACE
160 //@{
161 // mode of display for debug
162 enum TDebugDisplayMode { NoText = 0, PSName, SpawnDate, DebugModeCount };
163 // handle to add/remove a group of managed fxs (see add() / remove())
164 typedef TManagedFXGroupList::iterator TFXGroupHandle;
165 // dtor
166 ~CTimedFXManager();
167 /** Init the manager. Must be called before first use
168 * \param scene The scene from which instances are created
169 * \param startDate Date of init
170 * \param dayLength Length of a day, in hours
171 * \param noiseFrequency Frequency of noise used to compute pseudo random spwaning dates of fxs (depends on their spawn position and on the date)
172 * \param maxNumberOfFXInstance Max number of fx instances that are allowed to be instanciated at a given time. Nearest fx are instanciated first
173 * \param sortDistanceInterval precision with which fx are sorted in distance. For example, with 1meter precision, fx at 0.2 & 0.5 from the user are considered
174 * to be at the same distance
175 * \param maxDist Max dist at which fxs are sorted. For efficiency, it is important to keep maxDist / sortDistanceInterval
177 void init(NL3D::UScene *scene,
178 const CClientDate &startDate,
179 float dayLength,
180 float noiseFrequency,
181 uint maxNumberOfFXInstances,
182 float sortDistanceInterval,
183 float maxDist
185 // Reset all manager content
186 void reset();
187 /** Register a set of fxs to be managed.
188 * A handle is returned to remove it later.
190 TFXGroupHandle add(const std::vector<CTimedFX> &fxs, EGSPD::CSeason::TSeason season);
191 /** Remove a FX group that has previously been added
192 * All FX instances are deleted.
194 void remove(TFXGroupHandle handle);
195 /** Delayed removal of a fx group that has previously been added.
196 * All FXs are shutdown by removing their emitters.
197 * This is useful to switch from one season to another.
199 void shutDown(TFXGroupHandle handle);
200 // Update the manager state to match the new date. This add / removes FX as necessary
201 void update(const CClientDate &date, EGSPD::CSeason::TSeason currSeason, const NLMISC::CVector &camPos);
202 // Set a new date, but do not update current fx. The new hour will be taken in account during the next call to 'add'
203 void setDate(const CClientDate &date);
204 // get the current date
205 const CClientDate &getDate() const { return _CurrDate; }
206 // Access to the unique instance of this class
207 static CTimedFXManager &getInstance();
208 // for debug only
209 void dumpFXToAdd() const;
210 void dumpFXToRemove() const;
211 void dumpFXInfo() const;
212 // debug bbox and dates of FXs to remove and to add.
213 void displayFXBoxes(TDebugDisplayMode displayMode) const;
214 // set max number of fx to be instanciated at a time
215 void setMaxNumFXInstances(uint maxNumInstaces);
216 //@}
217 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
218 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
219 private:
220 // Set of fx to be instanciated in the future. It is managed as a priority queue (sorted by date of instanciation).
221 TTimeStampedFXPtrSet _FXToAdd;
222 // Set of fx to remove in the future, and that are currently instanciated (and are not shutting done). It is managed as a priority queue (sorted by date of removal).
223 TTimeStampedFXPtrSet _FXToRemove;
224 // List of the groups of FXs that are currenlty managed.
225 TManagedFXGroupList _FXGroups;
226 // The scene from which to add / remove instances
227 NL3D::UScene *_Scene;
228 // Current date of the manager
229 CClientDate _CurrDate;
230 // List of group that are shutting down (that is, shutDown(TFXGroupHandle handle) was called on that group)
231 std::list<TFXGroupHandle> _ShuttingDownGroups;
232 // Length of a day, in hours
233 float _DayLength;
234 // Noise function used to compute start/end date of fxs
235 NLMISC::CNoiseValue _Noise;
236 // Init
237 bool _InitDone;
239 //\name DISTANCE SORTING
240 //@{
241 // FX to be displayed can be limited in number -> the nearest fx are instanciated in priority
242 // To achieve this, we keep a list of candidate fx for each interval of distance (thus achieving linear approximate sorting)
244 typedef std::vector<CManagedFX *> TCandidateFXListSortedByDist;
245 TCandidateFXListSortedByDist _CandidateFXListSortedByDist; // roughly sorted list of candidate fx. Should be rebuilt completely when players moves (done in linear time)
246 TCandidateFXListSortedByDist _CandidateFXListSortedByDistTmp; // already allocated vect for fast resorting of list when player moves
248 // NB : this vector nevers grows
249 bool _CandidateFXListTouched; // the list of candidate has been modified, so the manager should see which fxs should be instanciated, and which fxs should be removed
250 float _SortDistance; // length of each distance interval, in meters
251 uint _MaxNumberOfFXInstances; // max number of instances that can be 'alive' at a time
252 //@}
254 // Linked list of currently instanciated FXs (nearest candidates)
255 CManagedFX *_InstanciatedFXs;
256 NLMISC::CVector _LastCamPos;
258 // fx manager to deals with shutting down fxs
259 CFXManager _FXManager;
261 private:
262 // ctor
263 CTimedFXManager();
264 // for debug
265 void checkIntegrity();
266 // setup user params for a fx
267 void setupUserParams(CManagedFX &fi, uint cycle);
268 // insert a fx in list of candidate for instanciation (also unlink from a previous list)
269 void linkCandidateFX(TCandidateFXListSortedByDist &targetList, float dist, CManagedFX *fx);
270 // link a fx into a list of instances (also unlink from a previous list)
271 void linkInstanciatedFX(CManagedFX *&listHead, CManagedFX *fx);
272 // update list of instanciated fxs (create / removes fxs as necessary)
273 void updateInstanciatedFXList();
274 // re-sort list of candidate fx by distance (this is necessary when player moves)
275 void updateCandidateFXListSorting();
276 public:
277 // convert a cycle and an hour to a date
278 static void cycleToDate(sint32 cycle, float hour, float cycleLength, float dayLength, CClientDate &result);
279 // give the matching cycle for a date
280 static sint32 dateToCycle(const CClientDate &date, float cycleLength, float dayLength);
285 #endif