/**************************************************************************** Copyright (c) 2015-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. https://axmolengine.github.io/ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #ifndef __AX_PARTICLE_SYSTEM_3D_H__ #define __AX_PARTICLE_SYSTEM_3D_H__ #include "2d/CCNode.h" #include "math/CCMath.h" #include <vector> #include <map> #include <list> #include "ExtensionExport.h" NS_AX_BEGIN /** * 3d particle system */ class Particle3DEmitter; class Particle3DAffector; class Particle3DRender; struct AX_EX_DLL Particle3D { Particle3D(); virtual ~Particle3D(); // property of particles Vec3 position; // position Quaternion orientation; // Orientation of the particle. Vec4 color; // particle color Vec2 lb_uv; // left bottom uv Vec2 rt_uv; // right top uv float width; // Own width float height; // Own height float depth; // Own depth // user defined property std::unordered_map<std::string, void*> userDefs; }; template <typename T> class AX_EX_DLL DataPool { public: typedef typename std::list<T*> PoolList; typedef typename std::list<T*>::iterator PoolIterator; DataPool(){}; ~DataPool(){}; T* createData() { if (_locked.empty()) return nullptr; T* p = _locked.front(); //_released.emplace_back(p); //_locked.erase(_locked.begin()); _released.splice(_released.end(), _locked, _locked.begin()); return p; } void lockLatestData() { _locked.emplace_back(*_releasedIter); _releasedIter = _released.erase(_releasedIter); if (_releasedIter != _released.begin() && _releasedIter != _released.end()) { --_releasedIter; } } void lockData(T* data) { PoolIterator tempIter = _releasedIter; T* ptr = getFirst(); while (ptr) { if (ptr == data) break; ptr = getNext(); } if (ptr) lockLatestData(); _releasedIter = tempIter; } void lockAllDatas() { _locked.splice(_locked.end(), _released); //_locked.insert(_locked.end(), _released.begin(), _released.end()); //_released.clear(); _releasedIter = _released.begin(); } T* getFirst() { _releasedIter = _released.begin(); if (_releasedIter == _released.end()) return nullptr; return *_releasedIter; } T* getNext() { if (_releasedIter == _released.end()) return nullptr; ++_releasedIter; if (_releasedIter == _released.end()) return nullptr; return *_releasedIter; } const PoolList& getActiveDataList() const { return _released; }; const PoolList& getUnActiveDataList() const { return _locked; }; void addData(T* data) { _locked.emplace_back(data); } bool empty() const { return _released.empty(); }; void removeAllDatas() { lockAllDatas(); for (auto&& iter : _locked) { delete iter; } _locked.clear(); } private: PoolIterator _releasedIter; PoolList _released; PoolList _locked; }; typedef DataPool<Particle3D> ParticlePool; class AX_EX_DLL ParticleSystem3D : public Node, public BlendProtocol { public: enum class State { STOP, RUNNING, PAUSE, }; /** * override function */ virtual void update(float delta) override; /** * override function */ virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * override function */ virtual void setBlendFunc(const BlendFunc& blendFunc) override; /** * override function */ virtual const BlendFunc& getBlendFunc() const override; /** * particle system play control */ virtual void startParticleSystem(); /** * stop particle */ virtual void stopParticleSystem(); /** * pause particle */ virtual void pauseParticleSystem(); /** * resume particle */ virtual void resumeParticleSystem(); /** * set emitter for particle system, can set your own particle emitter */ void setEmitter(Particle3DEmitter* emitter); /** * set particle render, can set your own particle render */ void setRender(Particle3DRender* render); /** * return particle render */ Particle3DRender* getRender() { return _render; } /** * add particle affector */ void addAffector(Particle3DAffector* affector); /** * remove affector by index */ void removeAffector(int index); /** * remove all particle affector */ void removeAllAffector(); /** * get particle quota */ unsigned int getParticleQuota() const; /** * set particle quota */ void setParticleQuota(unsigned int quota); /** * get particle affector by index */ Particle3DAffector* getAffector(int index); /** * get particle pool */ const ParticlePool& getParticlePool() { return _particlePool; } /** * get alive particles count */ virtual int getAliveParticleCount() const { return 0; } /** * get particle playing state */ State getState() const { return _state; } bool isKeepLocal() const { return _keepLocal; } void setKeepLocal(bool keepLocal); /** *Enables or disables the system. */ void setEnabled(bool enabled); /** * is enabled */ bool isEnabled() const { return _isEnabled; } ParticleSystem3D(); virtual ~ParticleSystem3D(); protected: State _state; Particle3DEmitter* _emitter; std::vector<Particle3DAffector*> _affectors; Particle3DRender* _render; // particles ParticlePool _particlePool; int _aliveParticlesCnt; unsigned int _particleQuota; BlendFunc _blend; bool _keepLocal; bool _isEnabled; }; NS_AX_END #endif