347 lines
12 KiB
C++
347 lines
12 KiB
C++
// Ryzom - MMORPG Framework <http://dev.ryzom.com/projects/ryzom/>
|
|
// Copyright (C) 2010 Winch Gate Property Limited
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as
|
|
// published by the Free Software Foundation, either version 3 of the
|
|
// License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#ifndef CL_TIMED_FX_MANAGER_H
|
|
#define CL_TIMED_FX_MANAGER_H
|
|
|
|
#include "nel/misc/vector.h"
|
|
#include "nel/misc/noise_value.h"
|
|
#include "game_share/season.h"
|
|
#include "time_client.h"
|
|
#include "fx_manager.h"
|
|
|
|
class CSeasonFXSheet;
|
|
|
|
namespace NL3D
|
|
{
|
|
class UParticleSystemInstance;
|
|
class UScene;
|
|
}
|
|
|
|
/** A fx that must be spawn at a given season and hour
|
|
* \author Nicolas Vizerie
|
|
* \author Nevrax France
|
|
* \date 2003
|
|
*/
|
|
class CTimedFX
|
|
{
|
|
public:
|
|
NLMISC::CVector SpawnPosition;
|
|
NLMISC::CQuat Rot;
|
|
NLMISC::CVector Scale;
|
|
const CSeasonFXSheet *FXSheet;
|
|
#if !FINAL_VERSION
|
|
bool FromIG; // true if the fx comes from an ig, or false if it was generated dynamically
|
|
#endif
|
|
public:
|
|
CTimedFX() : SpawnPosition(0.f, 0.f, 0.f), FXSheet(NULL)
|
|
{
|
|
#if !FINAL_VERSION
|
|
FromIG = true;
|
|
#endif
|
|
}
|
|
NLMISC::CMatrix getInstanceMatrix() const;
|
|
};
|
|
|
|
typedef std::vector<CTimedFX> TTimedFXGroup;
|
|
|
|
/** Manager to spawn fxs at a given season and hour.
|
|
* \author Nicolas Vizerie
|
|
* \author Nevrax France
|
|
* \date 2003
|
|
*/
|
|
class CTimedFXManager
|
|
{
|
|
private:
|
|
class CManagedFX;
|
|
struct CTimeStampedFX
|
|
{
|
|
CClientDate Date; // the date at which the FX must be added / removed
|
|
//sint32 DebugDay;
|
|
CManagedFX *FX; // managed FX
|
|
bool operator < (const CTimeStampedFX &rhs) const
|
|
{
|
|
if (Date == rhs.Date) return FX < rhs.FX;
|
|
else return Date < rhs.Date;
|
|
} // we want to deal with early dates sooner
|
|
bool operator == (const CTimeStampedFX &rhs) const { return Date == rhs.Date && FX == rhs.FX; }
|
|
CTimeStampedFX() : FX(NULL) {}
|
|
};
|
|
typedef std::set<CTimeStampedFX> TTimeStampedFXPtrSet;
|
|
struct CManagedFXGroup;
|
|
struct CCandidateFXListHead;
|
|
/** A managed FX. Unless it is flagged as 'always intanciated', or is in a group that is shutting down,
|
|
* 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.
|
|
* and will be removed in the future.
|
|
*/
|
|
class CManagedFX : public CTimedFX
|
|
{
|
|
public:
|
|
enum TState { Unknown = 0, Permanent, InAddList, InRemoveList };
|
|
#ifdef NL_DEBUG
|
|
CManagedFXGroup *OwnerGroup;
|
|
#endif
|
|
NL3D::UParticleSystemInstance Instance; // Pointer to the actual FX. NULL if failed to instanciate or if not instanciated
|
|
TState State;
|
|
TTimeStampedFXPtrSet::iterator SetHandle; // if the fx is in a list (see its state), then it is an iterator into that list (for removal)
|
|
//
|
|
CManagedFX **_PrevCandidateFX; // if the fx has asked to be instanciated, it is inserted in a list of candidate fxs. points the previous "Next" pointer
|
|
// even if the fx is currently instanciated, it remains in that list (those are the potnetially instanciated fxs)
|
|
CManagedFX *_NextCandidateFX; // next candidate FX
|
|
//
|
|
CManagedFX **_PrevInstanciatedFX; // link into instanciated fx list, prev (is also a candidate)
|
|
CManagedFX *_NextInstanciatedFX; // link into instanciated fx list, next
|
|
// Tmp for debug
|
|
#ifdef NL_DEBUG
|
|
uint32 Magic;
|
|
#endif
|
|
public:
|
|
// ctor
|
|
CManagedFX()
|
|
{
|
|
Instance = NULL;
|
|
State = Unknown;
|
|
#ifdef NL_DEBUG
|
|
OwnerGroup = NULL;
|
|
Magic = 0xbaadcafe;
|
|
#endif
|
|
_PrevCandidateFX = NULL;
|
|
_NextCandidateFX = NULL;
|
|
//
|
|
_PrevInstanciatedFX = NULL;
|
|
_NextInstanciatedFX = NULL;
|
|
}
|
|
// compute start hour of that fx for the given day
|
|
void computeStartHour(sint32 cycle, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv) const;
|
|
// compute end hour of that fx for the given day
|
|
void computeEndHour(sint32 cycle, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv) const;
|
|
// unlink from list of candidate fxs
|
|
void unlinkFromCandidateFXList();
|
|
// unlink from list of instanciated fx. NB : this doesn't remove the model!
|
|
void unlinkFromInstanciatedFXList();
|
|
/** Shutdown the fx
|
|
*/
|
|
void shutDown(NL3D::UScene *scene, CFXManager &fxManager);
|
|
private:
|
|
void computeHour(sint32 cycle, float bias, CClientDate &resultDate, float cycleLength, float dayLength, const NLMISC::CNoiseValue &nv, float minHour, float maxHour) const;
|
|
};
|
|
// A group of managed fx. We never resize these vectors after creation so we can keep pointers in them.
|
|
typedef std::vector<CManagedFX> TManagedFXGroup;
|
|
struct CManagedFXGroup
|
|
{
|
|
TManagedFXGroup Group;
|
|
#ifdef NL_DEBUG
|
|
EGSPD::CSeason::TSeason Season;
|
|
#endif
|
|
};
|
|
// a list of group of managed fxs.
|
|
typedef std::list<CManagedFXGroup> TManagedFXGroupList;
|
|
|
|
|
|
public:
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
//\name USER INTERFACE
|
|
//@{
|
|
// mode of display for debug
|
|
enum TDebugDisplayMode { NoText = 0, PSName, SpawnDate, DebugModeCount };
|
|
// handle to add/remove a group of managed fxs (see add() / remove())
|
|
typedef TManagedFXGroupList::iterator TFXGroupHandle;
|
|
// dtor
|
|
~CTimedFXManager();
|
|
/** Init the manager. Must be called before first use
|
|
* \param scene The scene from which instances are created
|
|
* \param startDate Date of init
|
|
* \param dayLength Length of a day, in hours
|
|
* \param noiseFrequency Frequency of noise used to compute pseudo random spwaning dates of fxs (depends on their spawn position and on the date)
|
|
* \param maxNumberOfFXInstance Max number of fx instances that are allowed to be instanciated at a given time. Nearest fx are instanciated first
|
|
* \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
|
|
* to be at the same distance
|
|
* \param maxDist Max dist at which fxs are sorted. For efficiency, it is important to keep maxDist / sortDistanceInterval
|
|
*/
|
|
void init(NL3D::UScene *scene,
|
|
const CClientDate &startDate,
|
|
float dayLength,
|
|
float noiseFrequency,
|
|
uint maxNumberOfFXInstances,
|
|
float sortDistanceInterval,
|
|
float maxDist
|
|
);
|
|
// Reset all manager content
|
|
void reset();
|
|
/** Register a set of fxs to be managed.
|
|
* A handle is returned to remove it later.
|
|
*/
|
|
TFXGroupHandle add(const std::vector<CTimedFX> &fxs, EGSPD::CSeason::TSeason season);
|
|
/** Remove a FX group that has previously been added
|
|
* All FX instances are deleted.
|
|
*/
|
|
void remove(TFXGroupHandle handle);
|
|
/** Delayed removal of a fx group that has previously been added.
|
|
* All FXs are shutdown by removing their emitters.
|
|
* This is useful to switch from one season to another.
|
|
*/
|
|
void shutDown(TFXGroupHandle handle);
|
|
// Update the manager state to match the new date. This add / removes FX as necessary
|
|
void update(const CClientDate &date, EGSPD::CSeason::TSeason currSeason, const NLMISC::CVector &camPos);
|
|
// Set a new date, but do not update current fx. The new hour will be taken in account during the next call to 'add'
|
|
void setDate(const CClientDate &date);
|
|
// get the current date
|
|
const CClientDate &getDate() const { return _CurrDate; }
|
|
// Access to the unique instance of this class
|
|
static CTimedFXManager &getInstance();
|
|
// for debug only
|
|
void dumpFXToAdd() const;
|
|
void dumpFXToRemove() const;
|
|
void dumpFXInfo() const;
|
|
// debug bbox and dates of FXs to remove and to add.
|
|
void displayFXBoxes(TDebugDisplayMode displayMode) const;
|
|
// set max number of fx to be instanciated at a time
|
|
void setMaxNumFXInstances(uint maxNumInstaces);
|
|
//@}
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
|
private:
|
|
// Set of fx to be instanciated in the future. It is managed as a priority queue (sorted by date of instanciation).
|
|
TTimeStampedFXPtrSet _FXToAdd;
|
|
// 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).
|
|
TTimeStampedFXPtrSet _FXToRemove;
|
|
// List of the groups of FXs that are currenlty managed.
|
|
TManagedFXGroupList _FXGroups;
|
|
// The scene from which to add / remove instances
|
|
NL3D::UScene *_Scene;
|
|
// Current date of the manager
|
|
CClientDate _CurrDate;
|
|
// List of group that are shutting down (that is, shutDown(TFXGroupHandle handle) was called on that group)
|
|
std::list<TFXGroupHandle> _ShuttingDownGroups;
|
|
// Length of a day, in hours
|
|
float _DayLength;
|
|
// Noise function used to compute start/end date of fxs
|
|
NLMISC::CNoiseValue _Noise;
|
|
// Init
|
|
bool _InitDone;
|
|
|
|
//\name DISTANCE SORTING
|
|
//@{
|
|
// FX to be displayed can be limited in number -> the nearest fx are instanciated in priority
|
|
// To achieve this, we keep a list of candidate fx for each interval of distance (thus achieving linear approximate sorting)
|
|
|
|
typedef std::vector<CManagedFX *> TCandidateFXListSortedByDist;
|
|
TCandidateFXListSortedByDist _CandidateFXListSortedByDist; // roughly sorted list of candidate fx. Should be rebuilt completely when players moves (done in linear time)
|
|
TCandidateFXListSortedByDist _CandidateFXListSortedByDistTmp; // already allocated vect for fast resorting of list when player moves
|
|
|
|
// NB : this vector nevers grows
|
|
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
|
|
float _SortDistance; // lenght of each distance interval, in meters
|
|
uint _MaxNumberOfFXInstances; // max number of instances that can be 'alive' at a time
|
|
//@}
|
|
|
|
// Linked list of currently instanciated FXs (nearest candidates)
|
|
CManagedFX *_InstanciatedFXs;
|
|
NLMISC::CVector _LastCamPos;
|
|
|
|
// fx manager to deals with shutting down fxs
|
|
CFXManager _FXManager;
|
|
|
|
private:
|
|
// ctor
|
|
CTimedFXManager();
|
|
// for debug
|
|
void checkIntegrity();
|
|
// setup user params for a fx
|
|
void setupUserParams(CManagedFX &fi, uint cycle);
|
|
// insert a fx in list of candidate for instanciation (also unlink from a previous list)
|
|
void linkCandidateFX(TCandidateFXListSortedByDist &targetList, float dist, CManagedFX *fx);
|
|
// link a fx into a list of instances (also unlink from a previous list)
|
|
void linkInstanciatedFX(CManagedFX *&listHead, CManagedFX *fx);
|
|
// update list of instanciated fxs (create / removes fxs as necessary)
|
|
void updateInstanciatedFXList();
|
|
// re-sort list of candidate fx by distance (this is necessary when player moves)
|
|
void updateCandidateFXListSorting();
|
|
public:
|
|
// convert a cycle and an hour to a date
|
|
static void cycleToDate(sint32 cycle, float hour, float cycleLength, float dayLength, CClientDate &result);
|
|
// give the matching cycle for a date
|
|
static sint32 dateToCycle(const CClientDate &date, float cycleLength, float dayLength);
|
|
};
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|