//----------------------------------------------------------------------------- // Copyright (c) 2013 GarageGames, LLC // // 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 _PARTICLE_PLAYER_H_ #define _PARTICLE_PLAYER_H_ #ifndef _PARTICLE_ASSET_H_ #include "2d/assets/ParticleAsset.h" #endif #ifndef _PARTICLE_SYSTEM_H_ #include "2d/core/ParticleSystem.h" #endif //----------------------------------------------------------------------------- #define PARTICLE_PLAYER_EMISSION_RATE_SCALE "$pref::T2D::ParticlePlayerEmissionRateScale" #define PARTICLE_PLAYER_SIZE_SCALE "$pref::T2D::ParticlePlayerSizeScale" #define PARTICLE_PLAYER_FORCE_SCALE "$pref::T2D::ParticlePlayerForceScale" #define PARTICLE_PLAYER_TIME_SCALE "$pref::T2D::ParticlePlayerTimeScale" //----------------------------------------------------------------------------- class ParticlePlayer : public SceneObject, protected AssetPtrCallback { private: typedef SceneObject Parent; /// Emitter node. class EmitterNode { private: ParticlePlayer* mOwner; ParticleAssetEmitter* mpAssetEmitter; ParticleSystem::ParticleNode mParticleNodeHead; F32 mTimeSinceLastGeneration; bool mPaused; bool mVisible; public: EmitterNode( ParticlePlayer* pParticlePlayer, ParticleAssetEmitter* pParticleAssetEmitter ) { // Sanity! AssertFatal( pParticlePlayer != NULL, "EmitterNode() - Cannot have a NULL owner." ); AssertFatal( pParticleAssetEmitter != NULL, "EmitterNode() - Cannot have a NULL particle asset emitter." ); // Set owner. mOwner = pParticlePlayer; // Set asset emitter. mpAssetEmitter = pParticleAssetEmitter; // Set emitter not paused. mPaused = false; // Set emitter visible. mVisible = true; // Reset time since last generation. mTimeSinceLastGeneration = 0.0f; // Reset the node head. mParticleNodeHead.mNextNode = mParticleNodeHead.mPreviousNode = &mParticleNodeHead; } ~EmitterNode() { freeAllParticles(); } inline ParticlePlayer* getOwner( void ) const { return mOwner; } inline ParticleAssetEmitter* getAssetEmitter( void ) const { return mpAssetEmitter; } inline bool getActiveParticles( void ) const { return mParticleNodeHead.mNextNode != &mParticleNodeHead; } inline ParticleSystem::ParticleNode* getFirstParticle( void ) const { return mParticleNodeHead.mNextNode; } inline ParticleSystem::ParticleNode* getLastParticle( void ) const { return mParticleNodeHead.mPreviousNode; } inline ParticleSystem::ParticleNode* getParticleNodeHead( void ) { return &mParticleNodeHead; } inline void setTimeSinceLastGeneration( const F32 timeSinceLastGeneration ) { mTimeSinceLastGeneration = timeSinceLastGeneration; } inline F32 getTimeSinceLastGeneration( void ) const { return mTimeSinceLastGeneration; } inline void setPaused( const bool paused ) { mPaused = paused; } inline bool getPaused( void ) const { return mPaused; } inline void setVisible( const bool visible ) { mVisible = visible; } inline bool getVisible( void ) const { return mVisible; } ParticleSystem::ParticleNode* createParticle( void ); void freeParticle( ParticleSystem::ParticleNode* pParticleNode ); void freeAllParticles( void ); }; typedef Vector typeEmitterVector; AssetPtr mParticleAsset; typeEmitterVector mEmitters; bool mCameraIdle; F32 mCameraIdleDistance; bool mParticleInterpolation; bool mPlaying; bool mPaused; F32 mAge; F32 mEmissionRateScale; F32 mSizeScale; F32 mForceScale; F32 mTimeScale; bool mWaitingForParticles; bool mWaitingForDelete; public: ParticlePlayer(); virtual ~ParticlePlayer(); static void initPersistFields(); virtual void copyTo(SimObject* object); virtual void safeDelete( void ); virtual void preIntegrate( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats ); void integrateObject( const F32 totalTime, const F32 elapsedTime, DebugStats* pDebugStats ); void interpolateObject( const F32 timeDelta ); virtual bool validRender( void ) const { return mParticleAsset.notNull() && mParticleAsset->isAssetValid(); } virtual bool shouldRender( void ) const { return true; } virtual void sceneRender( const SceneRenderState* pSceneRenderState, const SceneRenderRequest* pSceneRenderRequest, BatchRender* pBatchRenderer ); virtual void sceneRenderOverlay( const SceneRenderState* sceneRenderState ); void setParticle( const char* pAssetId ); const char* getParticle( void ) const { return mParticleAsset->getAssetId(); } inline void setCameraIdleDistance( const F32 idleDistance ) { mCameraIdleDistance = idleDistance; mCameraIdle = false; } inline F32 getCameraIdleDistance( void ) const { return mCameraIdleDistance; } inline void setParticleInterpolation( const bool interpolation ) { mParticleInterpolation = interpolation; } inline bool getParticleInterpolation( void ) const { return mParticleInterpolation; } inline void setEmissionRateScale( const F32 scale ) { mEmissionRateScale = scale; } inline F32 getEmissionRateScale( void ) const { return mEmissionRateScale; } inline void setSizeScale( const F32 scale ) { mSizeScale = scale; } inline F32 getSizeScale( void ) const { return mSizeScale; } inline void setForceScale( const F32 scale ) { mForceScale = scale; } inline F32 getForceScale( void ) const { return mForceScale; } inline void setTimeScale( const F32 scale ) { mTimeScale = scale; } inline F32 getTimeScale( void ) const { return mTimeScale; } inline const U32 getEmitterCount( void ) const { return (U32)mEmitters.size(); } void setEmitterPaused( const bool paused, const U32 emitterIndex ); bool getEmitterPaused( const U32 emitterIndex ); void setEmitterVisible( const bool visible, const U32 emitterIndex ); bool getEmitterVisible( const U32 emitterIndex ); bool play( const bool resetParticles ); void stop( const bool waitForParticles, const bool killEffect ); inline bool getIsPlaying( void ) const { return mPlaying; }; inline void setPaused( const bool paused ) { mPaused = paused; } inline bool getPaused( void ) const { return mPaused; } /// Declare Console Object. DECLARE_CONOBJECT(ParticlePlayer); protected: virtual void OnRegisterScene( Scene* pScene ); virtual void OnUnregisterScene( Scene* pScene ); virtual void onAssetRefreshed( AssetPtrBase* pAssetPtrBase ); /// Particle Creation/Integration. void configureParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode ); void integrateParticle( EmitterNode* pEmitterNode, ParticleSystem::ParticleNode* pParticleNode, const F32 particleAge, const F32 elapsedTime ); /// Persistence. virtual void onTamlAddParent( SimObject* pParentObject ); static bool setParticle(void* obj, const char* data) { static_cast( obj )->setParticle(data); return false; }; static bool writeCameraIdleDistance( void* obj, StringTableEntry pFieldName ) { return static_cast( obj )->getCameraIdleDistance() > 0.0f; } static bool writeParticleInterpolation( void* obj, StringTableEntry pFieldName ) { return static_cast( obj )->getParticleInterpolation(); } static bool writeEmissionRateScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getEmissionRateScale() ); } static bool writeSizeScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getSizeScale() ); } static bool writeForceScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getForceScale() ); } static bool writeTimeScale( void* obj, StringTableEntry pFieldName ) { return !mIsOne( static_cast( obj )->getTimeScale() ); } private: void initializeParticleAsset( void ); void destroyParticleAsset( void ); }; #endif // _PARTICLE_PLAYER_H_