/** Game Develop - Particle System Extension Copyright (c) 2010-2012 Florian Rival (Florian.Rival@gmail.com) This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions: 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required. 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. */ #if defined(GD_IDE_ONLY) #include //Must be placed first, otherwise we get errors relative to "cannot convert 'const TCHAR*'..." in wx/msw/winundef.h #endif #include #include #include "GDL/Object.h" #include "GDL/ImageManager.h" #include "GDL/tinyxml/tinyxml.h" #include "GDL/FontManager.h" #include "GDL/Position.h" #include "GDL/XmlMacros.h" #include "GDL/RuntimeScene.h" #include "GDL/RuntimeGame.h" #include "GDL/Polygon.h" #include "GDL/CommonTools.h" #include "ParticleEmitterObject.h" #include "ParticleSystemWrapper.h" #include #include #if defined(GD_IDE_ONLY) #include "GDL/CommonTools.h" #include "GDCore/IDE/ArbitraryResourceWorker.h" #include "GDCore/IDE/Dialogs/MainFrameWrapper.h" #include "ParticleEmitterObjectEditor.h" #endif #if defined(GD_IDE_ONLY) sf::Texture ParticleEmitterObject::edittimeIconImage; sf::Sprite ParticleEmitterObject::edittimeIcon; #endif ParticleEmitterObject::ParticleEmitterObject(std::string name_) : Object(name_), #if defined(GD_IDE_ONLY) particleEditionSimpleMode(true), emissionEditionSimpleMode(true), gravityEditionSimpleMode(true), #endif particleSystem(new ParticleSystemWrapper), rendererType(Point), rendererParam1(3.0f), rendererParam2(1.0f), additive(true), tank(-1), flow(300), emitterForceMin(25.0f), emitterForceMax(65.0f), emitterXDirection(0.0f), emitterYDirection(1.0f), emitterZDirection(0.0f), emitterAngleA(0), emitterAngleB(90), zoneRadius(3.0f), particleGravityX(0.0f), particleGravityY(-100.0f), particleGravityZ(0.0f), friction(2.0f), particleLifeTimeMin(0.5f), particleLifeTimeMax(2.5f), redParam(Enabled), greenParam(Random), blueParam(Random), alphaParam(Mutable), sizeParam(Mutable), angleParam(Mutable), particleRed1(255.0f), particleRed2(255.0f), particleGreen1(51), particleGreen2(255), particleBlue1(51), particleBlue2(0.0f), particleAlpha1(204), particleAlpha2(0.0f), particleSize1(100.0f), particleSize2(100.0f), particleAngle1(0.0f), particleAngle2(0.0f), particleAlphaRandomness1(0), particleAlphaRandomness2(0), particleSizeRandomness1(0), particleSizeRandomness2(0), particleAngleRandomness1(0), particleAngleRandomness2(0), maxParticleNb(5000), hasSomeParticles(true), opacity( 255 ), colorR( 255 ), colorG( 255 ), colorB( 255 ) { } void ParticleEmitterObject::LoadFromXml(const TiXmlElement * elem) { GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("tank", tank); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("flow", flow); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterForceMin", emitterForceMin); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterForceMax", emitterForceMax); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterXDirection", emitterXDirection); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterYDirection", emitterYDirection); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterZDirection", emitterZDirection); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterAngleA", emitterAngleA); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("emitterAngleB", emitterAngleB); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("zoneRadius", zoneRadius); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleGravityX", particleGravityX); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleGravityY", particleGravityY); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleGravityZ", particleGravityZ); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("friction", friction); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleLifeTimeMin", particleLifeTimeMin); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleLifeTimeMax", particleLifeTimeMax); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleRed1", particleRed1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleRed2", particleRed2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleGreen1", particleGreen1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleGreen2", particleGreen2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleBlue1", particleBlue1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleBlue2", particleBlue2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAlpha1", particleAlpha1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAlpha2", particleAlpha2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("rendererParam1", rendererParam1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("rendererParam2", rendererParam2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleSize1", particleSize1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleSize2", particleSize2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAngle1", particleAngle1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAngle2", particleAngle2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAlphaRandomness1", particleAlphaRandomness1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAlphaRandomness2", particleAlphaRandomness2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleSizeRandomness1", particleSizeRandomness1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleSizeRandomness2", particleSizeRandomness2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAngleRandomness1", particleAngleRandomness1); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_FLOAT("particleAngleRandomness2", particleAngleRandomness2); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_BOOL("additive", additive); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("textureParticleName", textureParticleName); { int result = 5000; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("maxParticleNb", result); maxParticleNb = result; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("rendererType", result); if ( result == "Line") rendererType = Line; else if ( result == "Quad") rendererType = Quad; else rendererType = Point; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("redParam", result); if ( result == "Mutable") redParam = Mutable; else if ( result == "Random") redParam = Random; else redParam = Enabled; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("greenParam", result); if ( result == "Mutable") greenParam = Mutable; else if ( result == "Random") greenParam = Random; else greenParam = Enabled; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("blueParam", result); if ( result == "Mutable") blueParam = Mutable; else if ( result == "Random") blueParam = Random; else blueParam = Enabled; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("alphaParam", result); if ( result == "Mutable") alphaParam = Mutable; else if ( result == "Random") alphaParam = Random; else alphaParam = Enabled; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("sizeParam", result); if ( result == "Mutable") sizeParam = Mutable; else if ( result == "Random") sizeParam = Random; else sizeParam = Nothing; } { std::string result; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_STRING("angleParam", result); if ( result == "Mutable") angleParam = Mutable; else if ( result == "Random") angleParam = Random; else angleParam = Nothing; } int r,g,b; GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorR", r); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorG", g); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_INT("colorB", b); colorR = r; colorG = g; colorB = b; #if defined(GD_IDE_ONLY) GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_BOOL("particleEditionSimpleMode", particleEditionSimpleMode); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_BOOL("emissionEditionSimpleMode", emissionEditionSimpleMode); GD_CURRENT_ELEMENT_LOAD_ATTRIBUTE_BOOL("gravityEditionSimpleMode", gravityEditionSimpleMode); #endif } #if defined(GD_IDE_ONLY) void ParticleEmitterObject::SaveToXml(TiXmlElement * elem) { GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("tank", tank); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("flow", flow); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterForceMin", emitterForceMin); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterForceMax", emitterForceMax); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterXDirection", emitterXDirection); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterYDirection", emitterYDirection); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterZDirection", emitterZDirection); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterAngleA", emitterAngleA); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("emitterAngleB", emitterAngleB); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("zoneRadius", zoneRadius); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleGravityX", particleGravityX); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleGravityY", particleGravityY); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleGravityZ", particleGravityZ); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("friction", friction); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleLifeTimeMin", particleLifeTimeMin); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleLifeTimeMax", particleLifeTimeMax); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleRed1", particleRed1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleRed2", particleRed2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleGreen1", particleGreen1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleGreen2", particleGreen2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleBlue1", particleBlue1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleBlue2", particleBlue2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAlpha1", particleAlpha1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAlpha2", particleAlpha2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleSize1", particleSize1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleSize2", particleSize2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAngle1", particleAngle1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAngle2", particleAngle2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("rendererParam1", rendererParam1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("rendererParam2", rendererParam2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAlphaRandomness1", particleAlphaRandomness1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAlphaRandomness2", particleAlphaRandomness2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleSizeRandomness1", particleSizeRandomness1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleSizeRandomness2", particleSizeRandomness2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAngleRandomness1", particleAngleRandomness1); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_FLOAT("particleAngleRandomness2", particleAngleRandomness2); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_BOOL("additive", additive); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("textureParticleName", textureParticleName); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("maxParticleNb", maxParticleNb); std::string rendererTypeStr = "Point"; if ( rendererType == Line ) rendererTypeStr = "Line"; else if ( rendererType == Quad ) rendererTypeStr = "Quad"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("rendererType", rendererTypeStr); std::string redParamStr = "Enabled"; if ( redParam == Mutable ) redParamStr = "Mutable"; else if ( redParam == Random ) redParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("redParam", redParamStr); std::string greenParamStr = "Enabled"; if ( greenParam == Mutable ) greenParamStr = "Mutable"; else if ( greenParam == Random ) greenParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("greenParam", greenParamStr); std::string blueParamStr = "Enabled"; if ( blueParam == Mutable ) blueParamStr = "Mutable"; else if ( blueParam == Random ) blueParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("blueParam", blueParamStr); std::string alphaParamStr = "Enabled"; if ( alphaParam == Mutable ) alphaParamStr = "Mutable"; else if ( alphaParam == Random ) alphaParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("alphaParam", alphaParamStr); std::string sizeParamStr = "Nothing"; if ( sizeParam == Mutable ) sizeParamStr = "Mutable"; else if ( sizeParam == Random ) sizeParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("sizeParam", sizeParamStr); std::string angleParamStr = "Nothing"; if ( angleParam == Mutable ) angleParamStr = "Mutable"; else if ( angleParam == Random ) angleParamStr = "Random"; GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_STRING("angleParam", angleParamStr); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorR", colorR); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorG", colorG); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE("colorB", colorB); #if defined(GD_IDE_ONLY) GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_BOOL("particleEditionSimpleMode", particleEditionSimpleMode); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_BOOL("emissionEditionSimpleMode", emissionEditionSimpleMode); GD_CURRENT_ELEMENT_SAVE_ATTRIBUTE_BOOL("gravityEditionSimpleMode", gravityEditionSimpleMode); #endif } #endif /** * Create particle system from parameters */ void ParticleEmitterObject::CreateParticleSystem() { int enabledFlag = 0; int mutableFlag = 0; int randomFlag = 0; if ( redParam == Enabled ) enabledFlag |= SPK::FLAG_RED; else if ( redParam == Mutable ) { enabledFlag |= SPK::FLAG_RED; mutableFlag |= SPK::FLAG_RED; } else if ( redParam == Random ) { enabledFlag |= SPK::FLAG_RED; randomFlag |= SPK::FLAG_RED; } if ( greenParam == Enabled ) enabledFlag |= SPK::FLAG_RED; else if ( greenParam == Mutable ) { enabledFlag |= SPK::FLAG_GREEN; mutableFlag |= SPK::FLAG_GREEN; } else if ( greenParam == Random ) { enabledFlag |= SPK::FLAG_GREEN; randomFlag |= SPK::FLAG_GREEN; } if ( blueParam == Enabled ) enabledFlag |= SPK::FLAG_BLUE; else if ( blueParam == Mutable ) { enabledFlag |= SPK::FLAG_BLUE; mutableFlag |= SPK::FLAG_BLUE; } else if ( blueParam == Random ) { enabledFlag |= SPK::FLAG_BLUE; randomFlag |= SPK::FLAG_BLUE; } if ( alphaParam == Enabled ) enabledFlag |= SPK::FLAG_ALPHA; else if ( alphaParam == Mutable ) { enabledFlag |= SPK::FLAG_ALPHA; randomFlag |= SPK::FLAG_ALPHA; mutableFlag |= SPK::FLAG_ALPHA; } else if ( alphaParam == Random ) { enabledFlag |= SPK::FLAG_ALPHA; randomFlag |= SPK::FLAG_ALPHA; } if ( sizeParam == Mutable ) { enabledFlag |= SPK::FLAG_SIZE; randomFlag |= SPK::FLAG_SIZE; mutableFlag |= SPK::FLAG_SIZE; } else if ( sizeParam == Random ) { enabledFlag |= SPK::FLAG_SIZE; randomFlag |= SPK::FLAG_SIZE; } if ( angleParam == Mutable ) { enabledFlag |= SPK::FLAG_ANGLE; randomFlag |= SPK::FLAG_ANGLE; mutableFlag |= SPK::FLAG_ANGLE; } else if ( angleParam == Random ) { enabledFlag |= SPK::FLAG_ANGLE; randomFlag |= SPK::FLAG_ANGLE; } if ( rendererType == Quad) enabledFlag |= SPK::PARAM_TEXTURE_INDEX; // Create the model particleSystem->particleModel = SPK::Model::create( enabledFlag, mutableFlag, randomFlag ); UpdateRedParameters(); UpdateGreenParameters(); UpdateBlueParameters(); UpdateAlphaParameters(); UpdateSizeParameters(); UpdateAngleParameters(); UpdateLifeTime(); // Create the renderer if ( rendererType == Line ) particleSystem->renderer = SPK::GL::GLLineRenderer::create(rendererParam1,rendererParam2); else if ( rendererType == Quad) { SPK::GL::GLQuadRenderer * quadRenderer = new SPK::GL::GLQuadRenderer(rendererParam1,rendererParam2); if ( particleSystem->openGLTextureParticle->GetOpenGLTexture() != 0 ) { quadRenderer->setTexturingMode(SPK::TEXTURE_2D); quadRenderer->setTexture(particleSystem->openGLTextureParticle->GetOpenGLTexture()); } particleSystem->renderer = quadRenderer; } else { SPK::GL::GLPointRenderer* pointRenderer = SPK::GL::GLPointRenderer::create(); pointRenderer->setType(SPK::POINT_CIRCLE); pointRenderer->setSize(rendererParam1); particleSystem->renderer = pointRenderer; } particleSystem->renderer->enableBlending(true); if ( additive ) particleSystem->renderer->setBlendingFunctions(GL_SRC_ALPHA,GL_ONE); else particleSystem->renderer->setBlendingFunctions(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); particleSystem->renderer->setTextureBlending(GL_MODULATE); //Texture color modulated with particle color particleSystem->renderer->enableRenderingHint(SPK::DEPTH_TEST,false); //No depth test for performance // Create the zone particleSystem->zone = SPK::Sphere::create(SPK::Vector3D(GetX()*0.25f, -GetY()*0.25f, 0.0f), zoneRadius); // Create the emitter particleSystem->emitter = SPK::SphericEmitter::create(SPK::Vector3D(emitterXDirection,-emitterYDirection,emitterZDirection), emitterAngleA/180.0f*3.14159f, emitterAngleB/180.0f*3.14159f); particleSystem->emitter->setForce(emitterForceMin,emitterForceMax); particleSystem->emitter->setZone(particleSystem->zone); particleSystem->emitter->setTank(tank); particleSystem->emitter->setFlow(flow); // Create the Group particleSystem->group = SPK::Group::create(particleSystem->particleModel, maxParticleNb); particleSystem->group->addEmitter(particleSystem->emitter); particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); particleSystem->group->setFriction(friction); particleSystem->group->setRenderer(particleSystem->renderer); // Create the System particleSystem->particleSystem = SPK::System::create(); particleSystem->particleSystem->addGroup(particleSystem->group); } void ParticleEmitterObject::UpdateRedParameters() { if ( !particleSystem->particleModel ) return; if ( redParam == Mutable || redParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_RED, particleRed1/255.0f,particleRed2/255.0f); else particleSystem->particleModel->setParam(SPK::PARAM_RED, particleRed1/255.0f); } void ParticleEmitterObject::UpdateGreenParameters() { if ( !particleSystem->particleModel ) return; if ( greenParam == Mutable || greenParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_GREEN, particleGreen1/255.0f,particleGreen2/255.0f); else particleSystem->particleModel->setParam(SPK::PARAM_GREEN, particleGreen1/255.0f); } void ParticleEmitterObject::UpdateBlueParameters() { if ( !particleSystem->particleModel ) return; if ( blueParam == Mutable || blueParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_BLUE, particleBlue1/255.0f,particleBlue2/255.0f); else particleSystem->particleModel->setParam(SPK::PARAM_BLUE, particleBlue1/255.0f); } void ParticleEmitterObject::UpdateAlphaParameters() { if ( !particleSystem->particleModel ) return; if ( alphaParam == Mutable ) particleSystem->particleModel->setParam(SPK::PARAM_ALPHA, (particleAlpha1-particleAlphaRandomness1/2.0f)/255.0f, (particleAlpha1+particleAlphaRandomness1/2.0f)/255.0f, (particleAlpha2-particleAlphaRandomness2/2.0f)/255.0f, (particleAlpha2+particleAlphaRandomness2/2.0f)/255.0f); else if ( alphaParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_ALPHA,(particleAlpha1)/255.0f,(particleAlpha2)/255.0f); else particleSystem->particleModel->setParam(SPK::PARAM_ALPHA, particleAlpha1/255.0f); } void ParticleEmitterObject::UpdateSizeParameters() { if ( !particleSystem->particleModel ) return; if ( sizeParam == Mutable ) particleSystem->particleModel->setParam(SPK::PARAM_SIZE, (particleSize1-particleSizeRandomness1/2.0f)/100.0f, (particleSize1+particleSizeRandomness1/2.0f)/100.0f, (particleSize2-particleSizeRandomness2/2.0f)/100.0f, (particleSize2+particleSizeRandomness2/2.0f)/100.0f); else if ( sizeParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_SIZE,(particleSize1)/100.0f, (particleSize2)/100.0f); else particleSystem->particleModel->setParam(SPK::PARAM_SIZE, particleSize1/100.0f); } void ParticleEmitterObject::UpdateAngleParameters() { if ( !particleSystem->particleModel ) return; if ( angleParam == Mutable ) particleSystem->particleModel->setParam(SPK::PARAM_ANGLE, -(particleAngle1-particleAngleRandomness1/2.0f)/180.0f*3.14159f, -(particleAngle1+particleAngleRandomness1/2.0f)/180.0f*3.14159f, -(particleAngle2-particleAngleRandomness2/2.0f)/180.0f*3.14159f, -(particleAngle2+particleAngleRandomness2/2.0f)/180.0f*3.14159f); else if ( angleParam == Random ) particleSystem->particleModel->setParam(SPK::PARAM_ANGLE, -(particleAngle1)/180.0f*3.14159f, -(particleAngle2)/180.0f*3.14159f); else particleSystem->particleModel->setParam(SPK::PARAM_ANGLE, -particleAngle1/180.0f*3.14159f); } void ParticleEmitterObject::UpdateLifeTime() { if ( !particleSystem->particleModel ) return; particleSystem->particleModel->setLifeTime(particleLifeTimeMin,particleLifeTimeMax); } bool ParticleEmitterObject::LoadRuntimeResources(const RuntimeScene & scene, const ImageManager & imageMgr ) { //Get the texture if necessary if ( rendererType == Quad ) particleSystem->openGLTextureParticle = imageMgr.GetOpenGLTexture(textureParticleName); CreateParticleSystem(); return true; } bool ParticleEmitterObject::LoadResources(const RuntimeScene & scene, const ImageManager & imageMgr) { #if defined(GD_IDE_ONLY) edittimeIconImage.LoadFromFile("Extensions/particleSystemSceneIcon.png"); edittimeIconImage.SetSmooth(false); edittimeIcon.SetTexture(edittimeIconImage); #endif return true; } ParticleEmitterObject::~ParticleEmitterObject() { if ( particleSystem ) delete particleSystem; } void ParticleEmitterObject::RecreateParticleSystem() { if ( particleSystem ) delete particleSystem; particleSystem = new ParticleSystemWrapper(); CreateParticleSystem(); } /** * Update animation and direction from the inital position */ bool ParticleEmitterObject::InitializeFromInitialPosition(const InitialPosition & position) { return true; } /** * Render object at runtime */ bool ParticleEmitterObject::Draw( sf::RenderTarget& renderTarget ) { //Don't draw anything if hidden if ( hidden ) return true; renderTarget.RestoreGLStates(); float xView = renderTarget.GetView().GetCenter().x*0.25f; float yView = -renderTarget.GetView().GetCenter().y*0.25f; glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glRotatef(renderTarget.GetView().GetRotation(), 0, 0, 1); glTranslatef(-xView, -yView, -75.0f*(renderTarget.GetView().GetSize().y/600.0f)); SPK::GL::GLRenderer::saveGLStates(); particleSystem->particleSystem->render(); SPK::GL::GLRenderer::restoreGLStates(); renderTarget.SaveGLStates(); return true; } void ParticleEmitterObject::OnPositionChanged() { if ( particleSystem->zone ) particleSystem->zone->setPosition(SPK::Vector3D(GetX()*0.25f, -GetY()*0.25f, 0)); } #if defined(GD_IDE_ONLY) /** * Render object at edittime */ bool ParticleEmitterObject::DrawEdittime(sf::RenderTarget& renderTarget) { sf::Shape circle = sf::Shape::Circle(sf::Vector2f(GetX(), GetY()), 3, sf::Color(particleRed1, particleGreen1, particleBlue1)); float emitterAngle = atan2(emitterYDirection, emitterXDirection); float line1Angle = emitterAngle-(emitterAngleB/2.0)/180.0*3.14159; float line2Angle = emitterAngle+(emitterAngleB/2.0)/180.0*3.14159; sf::Shape line1 = sf::Shape::Line(sf::Vector2f(GetX(), GetY()), sf::Vector2f(cos(line1Angle)*32+GetX(), sin(line1Angle)*32+GetY()), 1, sf::Color(particleRed2, particleGreen2, particleBlue2)); sf::Shape line2 = sf::Shape::Line(sf::Vector2f(GetX(), GetY()), sf::Vector2f(cos(line2Angle)*32+GetX(), sin(line2Angle)*32+GetY()), 1, sf::Color(particleRed2, particleGreen2, particleBlue2)); renderTarget.Draw(circle); renderTarget.Draw(line1); renderTarget.Draw(line2); return true; } void ParticleEmitterObject::ExposeResources(gd::ArbitraryResourceWorker & worker) { worker.ExposeImage(textureParticleName); } bool ParticleEmitterObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) { thumbnail = wxBitmap("Extensions/particleSystemicon24.png", wxBITMAP_TYPE_ANY); return true; } void ParticleEmitterObject::EditObject( wxWindow* parent, Game & game, gd::MainFrameWrapper & mainFrameWrapper ) { ParticleEmitterObjectEditor dialog(parent, game, *this, mainFrameWrapper); dialog.ShowModal(); } wxPanel * ParticleEmitterObject::CreateInitialPositionPanel( wxWindow* parent, const Game & game_, const Scene & scene_, const InitialPosition & position ) { return NULL; } void ParticleEmitterObject::UpdateInitialPositionFromPanel(wxPanel * panel, InitialPosition & position) { } void ParticleEmitterObject::GetPropertyForDebugger(unsigned int propertyNb, string & name, string & value) const { if ( !particleSystem->particleSystem ) return; if ( propertyNb == 0 ) {name = _("Particles number"); value = ToString(particleSystem->particleSystem->getNbParticles());} } bool ParticleEmitterObject::ChangeProperty(unsigned int propertyNb, string newValue) { if ( propertyNb == 0 ) { return false; } return true; } unsigned int ParticleEmitterObject::GetNumberOfProperties() const { return 1; } #endif void ParticleEmitterObject::SetTank(float newValue) { tank = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setFlow(tank); } void ParticleEmitterObject::SetFlow(float newValue) { flow = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setFlow(flow); } void ParticleEmitterObject::SetEmitterForceMin(float newValue) { emitterForceMin = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setForce(emitterForceMin, emitterForceMax); } void ParticleEmitterObject::SetEmitterForceMax(float newValue) { emitterForceMax = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setForce(emitterForceMin, emitterForceMax); } void ParticleEmitterObject::SetParticleGravityX(float newValue) { particleGravityX = newValue; if ( particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterObject::SetParticleGravityY(float newValue) { particleGravityY = newValue; if ( particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterObject::SetParticleGravityZ(float newValue) { particleGravityZ = newValue; if ( particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterObject::SetFriction(float newValue) { friction = newValue; if ( particleSystem->group ) particleSystem->group->setFriction(friction); } void ParticleEmitterObject::SetEmitterXDirection(float newValue) { emitterXDirection = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterObject::SetEmitterYDirection(float newValue) { emitterYDirection = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterObject::SetEmitterZDirection(float newValue) { emitterZDirection = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterObject::SetEmitterAngleA(float newValue) { emitterAngleA = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setAngles(emitterAngleA/180.0f*3.14159f, emitterAngleB/180.0f*3.14159f); } void ParticleEmitterObject::SetEmitterAngleB(float newValue) { emitterAngleB = newValue; if ( particleSystem->emitter ) particleSystem->emitter->setAngles(emitterAngleA/180.0f*3.14159f, emitterAngleB/180.0f*3.14159f); } void ParticleEmitterObject::SetZoneRadius(float newValue) { zoneRadius = newValue; if ( particleSystem->zone ) particleSystem->zone->setRadius(zoneRadius); } void ParticleEmitterObject::UpdateTime(float deltaTime) { hasSomeParticles = particleSystem->particleSystem->update (deltaTime); } void ParticleEmitterObject::SetParticleGravityAngle( float newAngleInDegree ) { float length = sqrt(GetParticleGravityY()*GetParticleGravityY()+GetParticleGravityX()*GetParticleGravityX()); SetParticleGravityX(cos(newAngleInDegree/180.0f*3.14159f)*length); SetParticleGravityY(sin(newAngleInDegree/180.0f*3.14159f)*length); } void ParticleEmitterObject::SetParticleGravityLength( float length ) { float angle = atan2(GetParticleGravityY(), GetParticleGravityX()); SetParticleGravityX(cos(angle)*length); SetParticleGravityY(sin(angle)*length); } float ParticleEmitterObject::GetParticleGravityAngle() const { return atan2(GetParticleGravityY(), GetParticleGravityX())*180.0f/3.14159f; } float ParticleEmitterObject::GetParticleGravityLength() const { return sqrt(GetParticleGravityY()*GetParticleGravityY()+GetParticleGravityX()*GetParticleGravityX()); } bool ParticleEmitterObject::SetAngle(float newAngleInDegrees) { SetEmitterXDirection(cos(newAngleInDegrees/180.0f*3.14159f)); SetEmitterYDirection(sin(newAngleInDegrees/180.0f*3.14159f)); return true; } float ParticleEmitterObject::GetAngle() const { return atan2f(GetEmitterYDirection(), GetEmitterXDirection())*180.0f/3.14159f; } void ParticleEmitterObject::SetParticleColor1( const std::string & color ) { vector < string > colors = SplitString (color, ';'); if ( colors.size() < 3 ) return; //Color is incorrect SetParticleRed1(ToInt(colors[0])); SetParticleBlue1(ToInt(colors[1])); SetParticleGreen1(ToInt(colors[2])); } void ParticleEmitterObject::SetParticleColor2( const std::string & color ) { vector < string > colors = SplitString (color, ';'); if ( colors.size() < 3 ) return; //Color is incorrect SetParticleRed2(ToInt(colors[0])); SetParticleBlue2(ToInt(colors[1])); SetParticleGreen2(ToInt(colors[2])); } /** * Change the texture */ void ParticleEmitterObject::SetTexture( RuntimeScene & scene, const std::string & textureParticleName ) { if ( rendererType == Quad ) { //Load new texture particleSystem->openGLTextureParticle = scene.game->imageManager->GetOpenGLTexture(textureParticleName); //Notify the renderer of the change SPK::GL::GLQuadRenderer * quadRenderer = dynamic_cast(particleSystem->renderer); if ( quadRenderer && particleSystem->openGLTextureParticle->GetOpenGLTexture() != 0 ) { quadRenderer->setTexturingMode(SPK::TEXTURE_2D); quadRenderer->setTexture(particleSystem->openGLTextureParticle->GetOpenGLTexture()); } } } /** * Get the real X position of the object */ float ParticleEmitterObject::GetDrawableX() const { return GetX()-32; } /** * Get the real Y position of the object */ float ParticleEmitterObject::GetDrawableY() const { return GetY()-32; } float ParticleEmitterObject::GetWidth() const { return 64; } float ParticleEmitterObject::GetHeight() const { return 64; } float ParticleEmitterObject::GetCenterX() const { return 32; } float ParticleEmitterObject::GetCenterY() const { return 32; } /** * Used by copy constructor and assignment operator. * \warning Do not forget to update me if members were changed! */ void ParticleEmitterObject::Init(const ParticleEmitterObject & other) { if ( particleSystem ) delete particleSystem; particleSystem = new ParticleSystemWrapper(*other.particleSystem); textureParticleName = other.textureParticleName; rendererType = other.rendererType; rendererParam1 = other.rendererParam1; rendererParam2 = other.rendererParam2; additive = other.additive; tank = other.tank; flow = other.flow; emitterForceMin = other.emitterForceMin; emitterForceMax = other.emitterForceMax; emitterXDirection = other.emitterXDirection; emitterYDirection = other.emitterYDirection; emitterZDirection = other.emitterZDirection; emitterAngleA = other.emitterAngleA; emitterAngleB = other.emitterAngleB; zoneRadius = other.zoneRadius; particleGravityX = other.particleGravityX; particleGravityY = other.particleGravityY; particleGravityZ = other.particleGravityZ; friction = other.friction; particleLifeTimeMin = other.particleLifeTimeMin; particleLifeTimeMax = other.particleLifeTimeMax; redParam = other.redParam; greenParam = other.greenParam; blueParam = other.blueParam; alphaParam = other.alphaParam; sizeParam = other.sizeParam; angleParam = other.angleParam; particleRed1 = other.particleRed1; particleRed2 = other.particleRed2; particleGreen1 = other.particleGreen1; particleGreen2 = other.particleGreen2; particleBlue1 = other.particleBlue1; particleBlue2 = other.particleBlue2; particleAlpha1 = other.particleAlpha1; particleAlpha2 = other.particleAlpha2; particleSize1 = other.particleSize1; particleSize2 = other.particleSize2; particleAngle1 = other.particleAngle1; particleAngle2 = other.particleAngle2; particleAlphaRandomness1 = other.particleAlphaRandomness1; particleAlphaRandomness2 = other.particleAlphaRandomness2; particleSizeRandomness1 = other.particleSizeRandomness1; particleSizeRandomness2 = other.particleSizeRandomness2; particleAngleRandomness1 = other.particleAngleRandomness1; particleAngleRandomness2 = other.particleAngleRandomness2; maxParticleNb = other.maxParticleNb; hasSomeParticles = other.hasSomeParticles; opacity = other.opacity; colorR = other.colorR; colorG = other.colorG; colorB = other.colorB; } /** * Function destroying an extension Object. * Game Develop does not delete directly extension object * to avoid overloaded new/delete conflicts. */ void DestroyParticleEmitterObject(Object * object) { delete object; } /** * Function creating an extension Object. * Game Develop can not directly create an extension object */ Object * CreateParticleEmitterObject(std::string name) { return new ParticleEmitterObject(name); }