//////////////////////////////////////////////////////////////////////////// // // Crytek Engine Source File. // Copyright (C), Crytek Studios, 2002. // ------------------------------------------------------------------------- // File name: particleeffect.cpp // Version: v1.00 // Created: 10/7/2003 by Timur. // Compilers: Visual Studio.NET // Description: // ------------------------------------------------------------------------- // History: // //////////////////////////////////////////////////////////////////////////// #include "StdAfx.h" #include "ParticleEffect.h" #include "ParticleEmitter.h" #include "PartMan.h" #include "3DEngine.h" #include "ISound.h" ////////////////////////////////////////////////////////////////////////// CParticleEffect::CParticleEffect( CPartManager *pPartManager ) { assert( pPartManager ); m_pPartManager = pPartManager; m_bLoaded = false; m_bEnabled = true; m_soundVolume = 100; m_soundMinRadius = 1; m_soundMaxRadius = 10; m_bSoundLoop = true; m_bOnEverySpawn = false; m_bAnimatedTexture[0] = false; m_bAnimatedTexture[1] = false; } ////////////////////////////////////////////////////////////////////////// CParticleEffect::~CParticleEffect() { UnloadResources(); } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetName( const char *sName ) { m_pPartManager->RenameEffect( this,sName ); m_name = sName; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetTexture( int process,const char *s ) { if (m_texture[process] != s) { UnloadResources(false); m_texture[process] = s; } }; ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetGeometry( int process,const char *s ) { if (m_geometry[process] != s) { UnloadResources(false); m_geometry[process] = s; } }; ////////////////////////////////////////////////////////////////////////// int CParticleEffect::GetChildCount() const { return (int)m_childs.size(); } ////////////////////////////////////////////////////////////////////////// IParticleEffect* CParticleEffect::GetChild( int index ) const { assert( index >= 0 && index < (int)m_childs.size() ); return m_childs[index]; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::AddChild( IParticleEffect *pEffect ) { assert( pEffect ); m_childs.push_back(pEffect); } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::RemoveChild( IParticleEffect *pEffect ) { assert( pEffect ); stl::find_and_erase( m_childs,pEffect ); } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::ClearChilds() { m_childs.clear(); } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::InsertChild( int slot,IParticleEffect *pEffect ) { if (slot < 0) slot = 0; if (slot > (int)m_childs.size()) slot = (int)m_childs.size(); assert( pEffect ); m_childs.insert( m_childs.begin() + slot,pEffect ); } ////////////////////////////////////////////////////////////////////////// int CParticleEffect::FindChild( IParticleEffect *pEffect ) const { for (int i = 0; i < (int)m_childs.size(); i++) { if (m_childs[i] == pEffect) { return i; } } return -1; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::LoadResources( bool bRecursive ) { if (m_bLoaded) return; m_bLoaded = true; for (int i = 0; i < NUM_PARTICLE_PROCESSES; i++) { if (!m_material[i].empty() && !m_pMaterials[i]) AssignMaterial( i ); bool bNeedAnimatedTex = m_particleParams[i].nTexAnimFramesCount > 0; // First unload what is loaded. if (m_particleParams[i].nTexId != 0) { GetRenderer()->RemoveTexture( m_particleParams[i].nTexId ); m_particleParams[i].nTexId = 0; if(m_particleParams[i].pAnimTex) GetRenderer()->RemoveAnimatedTexture(m_particleParams[i].pAnimTex); m_particleParams[i].pAnimTex = 0; } if (m_particleParams[i].pStatObj) { Get3DEngine()->ReleaseObject( m_particleParams[i].pStatObj ); m_particleParams[i].pStatObj = 0; } // Load textures. if (!m_texture[i].empty()) { if (bNeedAnimatedTex) { int texid = GetRenderer()->LoadAnimatedTexture( m_texture[i].c_str(),m_particleParams[i].nTexAnimFramesCount ); m_particleParams[i].nTexId = texid; m_particleParams[i].pAnimTex = GetRenderer()->GetAnimTexInfoFromId(texid); if(!m_particleParams[i].pAnimTex) { #if !defined(LINUX) Warning( 0,0,"ParticleEffect %s, Use Invalid Animated Texture Id %d",m_name.c_str(),texid ); #endif return; } } else { #if defined(NULL_RENDERER) m_particleParams[i].nTexId = 0; #else m_particleParams[i].nTexId = GetRenderer()->LoadTexture( m_texture[i].c_str() ); #endif m_particleParams[i].pAnimTex = 0; } m_bAnimatedTexture[i] = bNeedAnimatedTex; } // Load geometry. if (!m_geometry[i].empty()) { m_particleParams[i].pStatObj = Get3DEngine()->MakeObject( m_geometry[i].c_str() ); } } if (bRecursive) { for (int i = 0; i < (int)m_childs.size(); i++) { IParticleEffect *pChild = m_childs[i]; ((CParticleEffect*)pChild)->LoadResources( bRecursive ); } } } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::UnloadResources( bool bRecursive ) { if (!m_bLoaded) return; m_bLoaded = false; for (int i = 0; i < NUM_PARTICLE_PROCESSES; i++) { if (m_particleParams[i].nTexId != 0) { GetRenderer()->RemoveTexture( m_particleParams[i].nTexId ); m_particleParams[i].nTexId = 0; if(m_particleParams[i].pAnimTex) GetRenderer()->RemoveAnimatedTexture(m_particleParams[i].pAnimTex); m_particleParams[i].pAnimTex = 0; } if (m_particleParams[i].pStatObj) { Get3DEngine()->ReleaseObject( m_particleParams[i].pStatObj ); m_particleParams[i].pStatObj = 0; } } if (bRecursive) { for (int i = 0; i < (int)m_childs.size(); i++) { IParticleEffect *pChild = m_childs[i]; ((CParticleEffect*)pChild)->UnloadResources( bRecursive ); } } } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetSoundParams( const SoundParams ¶ms ) { m_sound = params.szSound; m_soundVolume = params.volume; m_soundMinRadius = params.minRadius; m_soundMaxRadius = params.maxRadius; m_bSoundLoop = params.bLoop; m_bOnEverySpawn = params.bOnEverySpawn; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::GetSoundParams( SoundParams ¶ms ) const { params.szSound = m_sound.c_str(); params.volume = m_soundVolume; params.minRadius = m_soundMinRadius; params.maxRadius = m_soundMaxRadius; params.bLoop = m_bSoundLoop; params.bOnEverySpawn = m_bOnEverySpawn; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::Spawn( const Vec3 &pos,const Vec3 &dir,float fScale ) { if (m_bEnabled) { // Spawn emitter for this particle. if (!IsResourcesLoaded()) { LoadResources(); } if (m_particleParams[1].nCount > 0) { m_particleParams[0].pChild = &m_particleParams[1]; } else m_particleParams[0].pChild = 0; m_particleParams[0].pEntity = 0; m_particleParams[1].pEntity = 0; // Spawn particle system emitter. CParticleEmitter *pEmitter = new CParticleEmitter(m_pPartManager); pEmitter->m_bPermament = false; pEmitter->AssignEffect( this,false ); pEmitter->SetPos( pos,dir,fScale ); } // Spawn child effects. for (int i = 0; i < (int)m_childs.size(); i++) { m_childs[i]->Spawn( pos,dir,fScale ); } } ////////////////////////////////////////////////////////////////////////// bool CParticleEffect::PrepareSpawn( const Vec3 &pos ) { if (!m_bEnabled) return false; if (!IsResourcesLoaded()) { LoadResources(); } /* // Play sound if not looped. if (!m_bSoundLoop && !m_sound.empty()) { ISound *pSound = GetSystem()->GetISoundSystem()->LoadSound( m_sound.c_str(),FLAG_SOUND_3D ); if (pSound) { pSound->SetVolume( (int)m_soundVolume ); pSound->SetMinMaxDistance( m_soundMinRadius,m_soundMaxRadius ); pSound->SetPosition(pos); pSound->Play(); } } */ // Init child process pointer. if (m_particleParams[1].nCount > 0) m_particleParams[0].pChild = &m_particleParams[1]; else m_particleParams[0].pChild = 0; return true; } ////////////////////////////////////////////////////////////////////////// bool CParticleEffect::IsResourcesLoaded() { bool bAnimatedTex0 = m_particleParams[0].nTexAnimFramesCount > 0; bool bAnimatedTex1 = m_particleParams[1].nTexAnimFramesCount > 0; if (bAnimatedTex0 != m_bAnimatedTexture[0] || bAnimatedTex1 != m_bAnimatedTexture[1]) { UnloadResources(false); } return m_bLoaded; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetMaterial( int process,IMatInfo *pMaterial ) { assert( process >= 0 && process < NUM_PARTICLE_PROCESSES ); m_pMaterials[process] = pMaterial; if (pMaterial) pMaterial->SetFlags(pMaterial->GetFlags()|MIF_WASUSED); m_particleParams[process].pMaterial = pMaterial; if (pMaterial) { m_material[process] = pMaterial->GetName(); } else m_material[process] = ""; } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::SetMaterialName( int process,const char *sMtlName ) { assert( process >= 0 && process < NUM_PARTICLE_PROCESSES ); m_material[process] = sMtlName; AssignMaterial( process ); } ////////////////////////////////////////////////////////////////////////// const char* CParticleEffect::GetMaterialName( int process ) const { assert( process >= 0 && process < NUM_PARTICLE_PROCESSES ); return m_material[process].c_str(); } ////////////////////////////////////////////////////////////////////////// void CParticleEffect::AssignMaterial( int process ) { assert( process >= 0 && process < NUM_PARTICLE_PROCESSES ); IMatInfo *pMtl = 0; if (m_material[process].empty()) { pMtl = 0; } else { pMtl = Get3DEngine()->FindMaterial( m_material[process].c_str() ); if (!pMtl) { #if !defined(LINUX) Warning( 0,0,"ParticleEffect %s material assign failed, Material %s not found",m_name.c_str(),m_material[process].c_str() ); #endif } } if(pMtl) pMtl->SetFlags(pMtl->GetFlags()|MIF_WASUSED); m_pMaterials[process] = pMtl; m_particleParams[process].pMaterial = pMtl; }