khanat-opennel-code/code/nel/tools/3d/object_viewer/particle_workspace.h

247 lines
No EOL
10 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// 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 NL_PARTICLE_WORKSPACE_H
#define NL_PARTICLE_WORKSPACE_H
#include "nel/misc/smart_ptr.h"
#include "nel/misc/stream.h"
#include "nel/3d/skeleton_model.h"
//
#include "ps_initial_pos.h"
namespace NL3D
{
class CParticleSystem;
class CParticleSystemModel;
class CshapeBank;
class CFontManager;
class CFontGenerator;
}
class CObjectViewer;
/** A workspace containing several fxs
* \author Nicolas Vizerie
* \author Nevrax France
* \date 2004
*/
class CParticleWorkspace
{
public:
// A node in the workspace
// Contains a particle system and its relative path
class CNode : public NLMISC::CRefCount
{
public:
void init(CParticleWorkspace *ws);
void setRelativePath(const std::string &relativePath);
const std::string &getRelativePath() const { return _RelativePath; }
std::string getFullPath() const;
std::string getFilename() const { return NLMISC::CFile::getFilename(_RelativePath); }
// Serial node information into workspace stream. This does not save the particle system shape, only a reference to its file
void serial(NLMISC::IStream &f);
// Save the particle system target file
void savePS() throw(NLMISC::EStream);
// Save particle system with an arbitrary filename
void savePSAs(const std::string &fullPath) throw(NLMISC::EStream);
// put back in the unloaded state
void unload();
/** Load the particle system target file
* \return true if loading succeed (false means that loading was ok, but this is not a particle system). Other cases throw an exception.
*/
bool loadPS() throw(NLMISC::EStream);
// create an empty particle system
void createEmptyPS();
// helper flag to know if a ps has been modified
bool isModified() const { return _Modified; }
void setModified(bool modified);
NL3D::CParticleSystem *getPSPointer() const { return _PS; }
NL3D::CParticleSystemModel *getPSModel() const { return _PSM; }
// See if this node ps has been loaded
bool isLoaded() const { return _PS != NULL; }
// Get the workspace in which this node is inserted
CParticleWorkspace *getWorkspace() const { return _WS; }
// Memorize current position of object in the system. Useful to play the system because instances can be created / deleted
void memorizeState();
// Restore state previously memorize. Is usually called when the user stops a particle system
void restoreState();
// Test if state is currenlty memorized
bool isStateMemorized() const;
// For edition : If the state of the system has been memorized, keep it on par with the system when it is modified
void removeLocated(NL3D::CPSLocated *loc);
// For edition : If the state of the system has been memorized, keep it on par with the system when it is modified
void removeLocatedBindable(NL3D::CPSLocatedBindable *lb);
// Returns the skeleton to which the ps is currently sticked
NL3D::CSkeletonModel *getParentSkel() const { return _ParentSkel; }
const std::string &getParentSkelName() const { return _ParentSkelName; }
const std::string &getParentBoneName() const { return _ParentBoneName; }
//
std::string getTriggerAnim() { return _TriggerAnim; }
void setTriggerAnim(const std::string &anim);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private:
std::string _TriggerAnim;
NL3D::CParticleSystem *_PS;
NL3D::CParticleSystemModel *_PSM;
NL3D::CShapeBank *_ShapeBank; // Keep a shape bank per node because we want the whole path to identify the ps, not just its filename
// (shape bank keeps the filename only)
std::string _RelativePath; // relative path from which the ps was inserted
// relative path is also a unique identifier for this ps in the workspace
CPSInitialPos _InitialPos; // initial pos of system. Allow to restore the initial instances of the system when doing start / stop
bool _Modified;
CParticleWorkspace *_WS;
NLMISC::CRefPtr<NL3D::CSkeletonModel> _ParentSkel;
bool _ResetAutoCount;
//
std::string _ParentSkelName;
std::string _ParentBoneName;
private:
void setup(NL3D::CParticleSystemModel &psm);
public:
bool getResetAutoCountFlag() const { return _ResetAutoCount; }
void setResetAutoCountFlag(bool reset) { _ResetAutoCount = reset; }
// stick to a skeleton
void stickPSToSkeleton(NL3D::CSkeletonModel *skel,
uint bone,
const std::string &parentSkelName, // for callback after loading
const std::string &parentBoneName
);
void unstickPSFromSkeleton();
private:
friend class CParticleWorkspace;
// Ctor
CNode();
public:
// DTor
~CNode();
};
// callback to know when a workspace node has been modified
struct IModificationCallback
{
virtual void workspaceModifiedFlagChanged(CParticleWorkspace &pw) = 0;
virtual void nodeModifiedFlagChanged(CNode &node) = 0;
virtual void nodeSkelParentChanged(CNode &node) = 0; // called when fx has been linked / unlinked from a skeleton parent
};
// sorting predicate
struct ISort
{
virtual bool less(const CNode &lhs, const CNode &rhs) const = 0;
};
// ctor
CParticleWorkspace();
// dtor
~CParticleWorkspace();
// Init the workspace for the given object viewer
// must be called prior to other methods
void init(CObjectViewer *ov,
const std::string &filename,
NL3D::CFontManager *fontManager,
NL3D::CFontGenerator *fontGenerator
);
// Set a new name for the workspace (not its filename)
void setName(const std::string &name);
std::string getName() const { return _Name; }
// Get the object viewer instance
CObjectViewer *getObjectViewer() const { return _OV; }
// Get the path in which workpsace is located with a trailing slash
std::string getPath() const;
std::string getFilename() const { return _Filename; }
// Get Number of nodes in the workspace
uint getNumNode() const { return (uint)_Nodes.size(); }
/** Get a node in workspace
* Can keep pointer safely as long as the node is not deleted
*/
CNode *getNode(uint index) const { return _Nodes[index]; }
// Get a node from a pointer on a particle system
CNode *getNodeFromPS(NL3D::CParticleSystem *ps) const;
/** Test if the workspace already contains a node with the given filename name
* NB : 2 node with the same name re not allowed, even if their path is different
*/
bool containsFile(std::string filename) const;
/** Add a node in the workspace. Will succeed only if fx filename does not already exist in the workspace.
* The node is in the 'unloaded' state, so caller must load it afterward.
* NB : no lookup is done, full path must be provided.
*
* \return pointer to new node, or NULL if already inserted
*/
CNode *addNode(const std::string &filenameWithFullPath) throw( NLMISC::Exception);
// remove a node by its index
void removeNode(uint index);
// remove a node by its pointer
void removeNode(CNode *ptr);
// Get index of a node from its pointer, or -1 if not found
sint getIndexFromNode(CNode *node) const;
/** Save the workspace structure. The target file is the one given when this object was created
* NB : ps shape are not saved, only the structure is. To save the shapes, call CNode::save()
*/
void save() throw(NLMISC::EStream);
/** Load the workspace structure. The target file is the one given when this object was created
* All nodes are in the 'unloaded" state, so it is to the caller to load them by calling load() on their node
*/
void load() throw(NLMISC::EStream);
// Test whether the structure of the workspace has been modified (does not test if ps inside the workspace have been modified)
bool isModified() const { return _Modified; }
// Test whether the content of the workspace has ben modified
bool isContentModified() const;
void touch() { setModifiedFlag(true); }
void clearModifiedFlag() { setModifiedFlag(false); }
// set a callback to know when a node is modified
void setModificationCallback(IModificationCallback *cb) { _ModificationCallback = cb; }
IModificationCallback *getModificationCallback() const { return _ModificationCallback; }
// Sort the workspace. The node pointer remains valid and unchanged
void sort(ISort &predicate);
// get font manager / font generator
NL3D::CFontGenerator *getFontGenerator() const { return _FontGenerator; }
NL3D::CFontManager *getFontManager() const { return _FontManager; }
// restick all objects, useful after loading
void restickAllObjects(CObjectViewer *ov);
private:
typedef std::vector<NLMISC::CSmartPtr<CNode> > TNodeVect;
TNodeVect _Nodes; // use smart ptr to avoir prb wih resize
std::string _Filename; // path + name of workspace
CObjectViewer *_OV;
bool _Modified; //
NL3D::CFontManager *_FontManager;
NL3D::CFontGenerator *_FontGenerator;
IModificationCallback *_ModificationCallback;
std::string _Name; // workspace user name
private:
// serial the object
void serial(NLMISC::IStream &f) throw(NLMISC::EStream);
// set the 'modified flag' and call the callback
void setModifiedFlag(bool modified);
public:
void nodeModified(CNode &node);
};
#endif