/** GDevelop - Particle System Extension Copyright (c) 2010-2015 Florian Rival (Florian.Rival@gmail.com) This project is released under the MIT License. */ #if defined(GD_IDE_ONLY) && !defined(GD_NO_WX_GUI) #include //Must be placed first, otherwise we get errors relative to "cannot convert 'const TCHAR*'..." in wx/msw/winundef.h #endif #include #include #include "GDCore/Tools/Localization.h" #include "GDCpp/Object.h" #include "GDCpp/ImageManager.h" #include "GDCpp/RuntimeGame.h" #include "GDCpp/Serialization/SerializerElement.h" #include "GDCpp/FontManager.h" #include "GDCpp/Position.h" #include "GDCpp/Serialization/SerializerElement.h" #include "GDCpp/RuntimeScene.h" #include "GDCpp/Project.h" #include "GDCpp/Polygon2d.h" #include "GDCpp/CommonTools.h" #include "ParticleEmitterObject.h" #include "ParticleSystemWrapper.h" #include #include #if defined(GD_IDE_ONLY) #include "GDCpp/CommonTools.h" #include "GDCore/IDE/ArbitraryResourceWorker.h" #include "GDCore/IDE/Dialogs/MainFrameWrapper.h" #include "ParticleEmitterObjectEditor.h" #endif using namespace std; ParticleEmitterBase::ParticleEmitterBase() : 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), destroyWhenNoParticles(true), particleSystem(NULL) { } ParticleEmitterObject::ParticleEmitterObject(std::string name_) : Object(name_) #if defined(GD_IDE_ONLY) ,particleEditionSimpleMode(true), emissionEditionSimpleMode(true), gravityEditionSimpleMode(true) #endif { } void ParticleEmitterObject::DoUnserializeFrom(gd::Project & project, const gd::SerializerElement & element) { ParticleEmitterBase::UnserializeFrom(element); #if defined(GD_IDE_ONLY) particleEditionSimpleMode = element.GetBoolAttribute("particleEditionSimpleMode"); emissionEditionSimpleMode = element.GetBoolAttribute("emissionEditionSimpleMode"); gravityEditionSimpleMode = element.GetBoolAttribute("gravityEditionSimpleMode"); #endif } void ParticleEmitterBase::UnserializeFrom(const gd::SerializerElement & element) { tank = element.GetDoubleAttribute("tank"); flow = element.GetDoubleAttribute("flow"); emitterForceMin = element.GetDoubleAttribute("emitterForceMin"); emitterForceMax = element.GetDoubleAttribute("emitterForceMax"); emitterXDirection = element.GetDoubleAttribute("emitterXDirection"); emitterYDirection = element.GetDoubleAttribute("emitterYDirection"); emitterZDirection = element.GetDoubleAttribute("emitterZDirection"); emitterAngleA = element.GetDoubleAttribute("emitterAngleA"); emitterAngleB = element.GetDoubleAttribute("emitterAngleB"); zoneRadius = element.GetDoubleAttribute("zoneRadius"); particleGravityX = element.GetDoubleAttribute("particleGravityX"); particleGravityY = element.GetDoubleAttribute("particleGravityY"); particleGravityZ = element.GetDoubleAttribute("particleGravityZ"); friction = element.GetDoubleAttribute("friction"); particleLifeTimeMin = element.GetDoubleAttribute("particleLifeTimeMin"); particleLifeTimeMax = element.GetDoubleAttribute("particleLifeTimeMax"); particleRed1 = element.GetDoubleAttribute("particleRed1"); particleRed2 = element.GetDoubleAttribute("particleRed2"); particleGreen1 = element.GetDoubleAttribute("particleGreen1"); particleGreen2 = element.GetDoubleAttribute("particleGreen2"); particleBlue1 = element.GetDoubleAttribute("particleBlue1"); particleBlue2 = element.GetDoubleAttribute("particleBlue2"); particleAlpha1 = element.GetDoubleAttribute("particleAlpha1"); particleAlpha2 = element.GetDoubleAttribute("particleAlpha2"); rendererParam1 = element.GetDoubleAttribute("rendererParam1"); rendererParam2 = element.GetDoubleAttribute("rendererParam2"); particleSize1 = element.GetDoubleAttribute("particleSize1"); particleSize2 = element.GetDoubleAttribute("particleSize2"); particleAngle1 = element.GetDoubleAttribute("particleAngle1"); particleAngle2 = element.GetDoubleAttribute("particleAngle2"); particleAlphaRandomness1 = element.GetDoubleAttribute("particleAlphaRandomness1"); particleAlphaRandomness2 = element.GetDoubleAttribute("particleAlphaRandomness2"); particleSizeRandomness1 = element.GetDoubleAttribute("particleSizeRandomness1"); particleSizeRandomness2 = element.GetDoubleAttribute("particleSizeRandomness2"); particleAngleRandomness1 = element.GetDoubleAttribute("particleAngleRandomness1"); particleAngleRandomness2 = element.GetDoubleAttribute("particleAngleRandomness2"); additive = element.GetBoolAttribute("additive"); destroyWhenNoParticles = element.GetBoolAttribute("destroyWhenNoParticles", false); textureParticleName = element.GetStringAttribute("textureParticleName"); maxParticleNb = element.GetIntAttribute("maxParticleNb", 5000); { std::string result = element.GetStringAttribute("rendererType"); if ( result == "Line") rendererType = Line; else if ( result == "Quad") rendererType = Quad; else rendererType = Point; } { std::string result = element.GetStringAttribute("redParam"); if ( result == "Mutable") redParam = Mutable; else if ( result == "Random") redParam = Random; else redParam = Enabled; } { std::string result = element.GetStringAttribute("greenParam"); if ( result == "Mutable") greenParam = Mutable; else if ( result == "Random") greenParam = Random; else greenParam = Enabled; } { std::string result = element.GetStringAttribute("blueParam"); if ( result == "Mutable") blueParam = Mutable; else if ( result == "Random") blueParam = Random; else blueParam = Enabled; } { std::string result = element.GetStringAttribute("alphaParam"); if ( result == "Mutable") alphaParam = Mutable; else if ( result == "Random") alphaParam = Random; else alphaParam = Enabled; } { std::string result = element.GetStringAttribute("sizeParam"); if ( result == "Mutable") sizeParam = Mutable; else if ( result == "Random") sizeParam = Random; else sizeParam = Nothing; } { std::string result = element.GetStringAttribute("angleParam"); if ( result == "Mutable") angleParam = Mutable; else if ( result == "Random") angleParam = Random; else angleParam = Nothing; } } #if defined(GD_IDE_ONLY) void ParticleEmitterObject::DoSerializeTo(gd::SerializerElement & element) const { element.SetAttribute("particleEditionSimpleMode", particleEditionSimpleMode); element.SetAttribute("emissionEditionSimpleMode", emissionEditionSimpleMode); element.SetAttribute("gravityEditionSimpleMode", gravityEditionSimpleMode); ParticleEmitterBase::SerializeTo(element); } void ParticleEmitterBase::SerializeTo(gd::SerializerElement & element) const { element.SetAttribute("tank", tank); element.SetAttribute("flow", flow); element.SetAttribute("emitterForceMin", emitterForceMin); element.SetAttribute("emitterForceMax", emitterForceMax); element.SetAttribute("emitterXDirection", emitterXDirection); element.SetAttribute("emitterYDirection", emitterYDirection); element.SetAttribute("emitterZDirection", emitterZDirection); element.SetAttribute("emitterAngleA", emitterAngleA); element.SetAttribute("emitterAngleB", emitterAngleB); element.SetAttribute("zoneRadius", zoneRadius); element.SetAttribute("particleGravityX", particleGravityX); element.SetAttribute("particleGravityY", particleGravityY); element.SetAttribute("particleGravityZ", particleGravityZ); element.SetAttribute("friction", friction); element.SetAttribute("particleLifeTimeMin", particleLifeTimeMin); element.SetAttribute("particleLifeTimeMax", particleLifeTimeMax); element.SetAttribute("particleRed1", particleRed1); element.SetAttribute("particleRed2", particleRed2); element.SetAttribute("particleGreen1", particleGreen1); element.SetAttribute("particleGreen2", particleGreen2); element.SetAttribute("particleBlue1", particleBlue1); element.SetAttribute("particleBlue2", particleBlue2); element.SetAttribute("particleAlpha1", particleAlpha1); element.SetAttribute("particleAlpha2", particleAlpha2); element.SetAttribute("particleSize1", particleSize1); element.SetAttribute("particleSize2", particleSize2); element.SetAttribute("particleAngle1", particleAngle1); element.SetAttribute("particleAngle2", particleAngle2); element.SetAttribute("rendererParam1", rendererParam1); element.SetAttribute("rendererParam2", rendererParam2); element.SetAttribute("particleAlphaRandomness1", particleAlphaRandomness1); element.SetAttribute("particleAlphaRandomness2", particleAlphaRandomness2); element.SetAttribute("particleSizeRandomness1", particleSizeRandomness1); element.SetAttribute("particleSizeRandomness2", particleSizeRandomness2); element.SetAttribute("particleAngleRandomness1", particleAngleRandomness1); element.SetAttribute("particleAngleRandomness2", particleAngleRandomness2); element.SetAttribute("additive", additive); element.SetAttribute("destroyWhenNoParticles", destroyWhenNoParticles); element.SetAttribute("textureParticleName", textureParticleName); element.SetAttribute("maxParticleNb", (int)maxParticleNb); std::string rendererTypeStr = "Point"; if ( rendererType == Line ) rendererTypeStr = "Line"; else if ( rendererType == Quad ) rendererTypeStr = "Quad"; element.SetAttribute("rendererType", rendererTypeStr); std::string redParamStr = "Enabled"; if ( redParam == Mutable ) redParamStr = "Mutable"; else if ( redParam == Random ) redParamStr = "Random"; element.SetAttribute("redParam", redParamStr); std::string greenParamStr = "Enabled"; if ( greenParam == Mutable ) greenParamStr = "Mutable"; else if ( greenParam == Random ) greenParamStr = "Random"; element.SetAttribute("greenParam", greenParamStr); std::string blueParamStr = "Enabled"; if ( blueParam == Mutable ) blueParamStr = "Mutable"; else if ( blueParam == Random ) blueParamStr = "Random"; element.SetAttribute("blueParam", blueParamStr); std::string alphaParamStr = "Enabled"; if ( alphaParam == Mutable ) alphaParamStr = "Mutable"; else if ( alphaParam == Random ) alphaParamStr = "Random"; element.SetAttribute("alphaParam", alphaParamStr); std::string sizeParamStr = "Nothing"; if ( sizeParam == Mutable ) sizeParamStr = "Mutable"; else if ( sizeParam == Random ) sizeParamStr = "Random"; element.SetAttribute("sizeParam", sizeParamStr); std::string angleParamStr = "Nothing"; if ( angleParam == Mutable ) angleParamStr = "Mutable"; else if ( angleParam == Random ) angleParamStr = "Random"; element.SetAttribute("angleParam", angleParamStr); } #endif void ParticleEmitterBase::CreateParticleSystem() { if (particleSystem) delete particleSystem; particleSystem = new ParticleSystemWrapper; 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 && 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(0, 0), 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 ParticleEmitterBase::UpdateRedParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateGreenParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateBlueParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateAlphaParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateSizeParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateAngleParameters() { if ( !particleSystem || !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 ParticleEmitterBase::UpdateLifeTime() { if ( !particleSystem || !particleSystem->particleModel ) return; particleSystem->particleModel->setLifeTime(particleLifeTimeMin,particleLifeTimeMax); } RuntimeParticleEmitterObject::RuntimeParticleEmitterObject(RuntimeScene & scene_, const gd::Object & object): RuntimeObject(scene_, object), hasSomeParticles(true) { const ParticleEmitterObject & particleEmitterObject = static_cast(object); ParticleEmitterBase::operator=(particleEmitterObject); //Store a pointer to the scene scene = &scene_; CreateParticleSystem(); SetTexture(scene_, GetParticleTexture()); OnPositionChanged(); } ParticleEmitterBase::~ParticleEmitterBase() { if ( particleSystem ) delete particleSystem; } /** * Render object at runtime */ bool RuntimeParticleEmitterObject::Draw( sf::RenderTarget& renderTarget ) { //Don't draw anything if hidden if ( hidden ) return true; renderTarget.popGLStates(); 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(); GetParticleSystem()->particleSystem->render(); SPK::GL::GLRenderer::restoreGLStates(); renderTarget.pushGLStates(); return true; } void RuntimeParticleEmitterObject::OnPositionChanged() { if ( GetParticleSystem() && GetParticleSystem()->zone ) GetParticleSystem()->zone->setPosition(SPK::Vector3D(GetX()*0.25f, -GetY()*0.25f, 0)); } #if defined(GD_IDE_ONLY) /** * Render object at edittime */ void ParticleEmitterObject::DrawInitialInstance(gd::InitialInstance & instance, sf::RenderTarget & renderTarget, gd::Project & project, gd::Layout & layout) { sf::CircleShape circle(3); circle.setPosition(sf::Vector2f(instance.GetX()-2, instance.GetY()-2)); circle.setFillColor(sf::Color(GetParticleRed1(), GetParticleGreen1(), GetParticleBlue1())); float emitterAngle = instance.GetAngle()/180.0*3.14159; float line1Angle = emitterAngle-(GetEmitterAngleB()/2.0)/180.0*3.14159; float line2Angle = emitterAngle+(GetEmitterAngleB()/2.0)/180.0*3.14159; sf::Vertex line1[] = { sf::Vertex(sf::Vector2f(instance.GetX(), instance.GetY()), sf::Color(GetParticleRed1(), GetParticleGreen1(), GetParticleBlue1())), sf::Vertex(sf::Vector2f(cos(line1Angle)*32+instance.GetX(), sin(line1Angle)*32+instance.GetY()), sf::Color(GetParticleRed2(), GetParticleGreen2(), GetParticleBlue2())) }; sf::Vertex line2[] = { sf::Vertex(sf::Vector2f(instance.GetX(), instance.GetY()), sf::Color(GetParticleRed1(), GetParticleGreen1(), GetParticleBlue1())), sf::Vertex(sf::Vector2f(cos(line2Angle)*32+instance.GetX(), sin(line2Angle)*32+instance.GetY()), sf::Color(GetParticleRed2(), GetParticleGreen2(), GetParticleBlue2())) }; renderTarget.draw(circle); renderTarget.draw(line1, 2, sf::Lines); renderTarget.draw(line2, 2, sf::Lines); } void ParticleEmitterObject::ExposeResources(gd::ArbitraryResourceWorker & worker) { std::string texture = GetParticleTexture(); worker.ExposeImage(texture); SetParticleTexture(texture); } bool ParticleEmitterObject::GenerateThumbnail(const gd::Project & project, wxBitmap & thumbnail) const { #if !defined(GD_NO_WX_GUI) thumbnail = wxBitmap("CppPlatform/Extensions/particleSystemicon24.png", wxBITMAP_TYPE_ANY); #endif return true; } void ParticleEmitterObject::EditObject( wxWindow* parent, gd::Project & game, gd::MainFrameWrapper & mainFrameWrapper ) { #if !defined(GD_NO_WX_GUI) ParticleEmitterObjectEditor dialog(parent, game, *this, mainFrameWrapper); dialog.ShowModal(); #endif } void RuntimeParticleEmitterObject::GetPropertyForDebugger(unsigned int propertyNb, string & name, string & value) const { if ( !GetParticleSystem() || !GetParticleSystem()->particleSystem ) return; if ( propertyNb == 0 ) {name = _("Particles number"); value = ToString(GetParticleSystem()->particleSystem->getNbParticles());} } bool RuntimeParticleEmitterObject::ChangeProperty(unsigned int propertyNb, string newValue) { if ( propertyNb == 0 ) { return false; } return true; } unsigned int RuntimeParticleEmitterObject::GetNumberOfProperties() const { return 1; } #endif void ParticleEmitterBase::SetTank(float newValue) { tank = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setFlow(tank); } void ParticleEmitterBase::SetFlow(float newValue) { flow = newValue; if ( particleSystem &&particleSystem->emitter ) particleSystem->emitter->setFlow(flow); } void ParticleEmitterBase::SetEmitterForceMin(float newValue) { emitterForceMin = newValue; if ( particleSystem &&particleSystem->emitter ) particleSystem->emitter->setForce(emitterForceMin, emitterForceMax); } void ParticleEmitterBase::SetEmitterForceMax(float newValue) { emitterForceMax = newValue; if ( particleSystem &&particleSystem->emitter ) particleSystem->emitter->setForce(emitterForceMin, emitterForceMax); } void ParticleEmitterBase::SetParticleGravityX(float newValue) { particleGravityX = newValue; if ( particleSystem &&particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterBase::SetParticleGravityY(float newValue) { particleGravityY = newValue; if ( particleSystem &&particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterBase::SetParticleGravityZ(float newValue) { particleGravityZ = newValue; if ( particleSystem &&particleSystem->group ) particleSystem->group->setGravity(SPK::Vector3D(particleGravityX,-particleGravityY,particleGravityZ)); } void ParticleEmitterBase::SetFriction(float newValue) { friction = newValue; if ( particleSystem &&particleSystem->group ) particleSystem->group->setFriction(friction); } void ParticleEmitterBase::SetEmitterXDirection(float newValue) { emitterXDirection = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterBase::SetEmitterYDirection(float newValue) { emitterYDirection = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterBase::SetEmitterZDirection(float newValue) { emitterZDirection = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setDirection(SPK::Vector3D(emitterXDirection, -emitterYDirection, emitterZDirection)); } void ParticleEmitterBase::SetEmitterAngleA(float newValue) { emitterAngleA = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setAngles(emitterAngleA/180.0f*3.14159f, emitterAngleB/180.0f*3.14159f); } void ParticleEmitterBase::SetEmitterAngleB(float newValue) { emitterAngleB = newValue; if ( particleSystem && particleSystem->emitter ) particleSystem->emitter->setAngles(emitterAngleA/180.0f*3.14159f, emitterAngleB/180.0f*3.14159f); } void ParticleEmitterBase::SetZoneRadius(float newValue) { zoneRadius = newValue; if ( particleSystem && particleSystem->zone ) particleSystem->zone->setRadius(zoneRadius); } void RuntimeParticleEmitterObject::UpdateTime(float deltaTime) { if ( GetParticleSystem() ) hasSomeParticles = GetParticleSystem()->particleSystem->update(deltaTime); if (GetDestroyWhenNoParticles() && !hasSomeParticles) DeleteFromScene(const_cast(*scene)); //Ugly const cast } void ParticleEmitterBase::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 ParticleEmitterBase::SetParticleGravityLength( float length ) { float angle = atan2(GetParticleGravityY(), GetParticleGravityX()); SetParticleGravityX(cos(angle)*length); SetParticleGravityY(sin(angle)*length); } float ParticleEmitterBase::GetParticleGravityAngle() const { return atan2(GetParticleGravityY(), GetParticleGravityX())*180.0f/3.14159f; } float ParticleEmitterBase::GetParticleGravityLength() const { return sqrt(GetParticleGravityY()*GetParticleGravityY()+GetParticleGravityX()*GetParticleGravityX()); } bool RuntimeParticleEmitterObject::SetAngle(float newAngleInDegrees) { SetEmitterXDirection(cos(newAngleInDegrees/180.0f*3.14159f)); SetEmitterYDirection(sin(newAngleInDegrees/180.0f*3.14159f)); return true; } float RuntimeParticleEmitterObject::GetAngle() const { return atan2f(GetEmitterYDirection(), GetEmitterXDirection())*180.0f/3.14159f; } void ParticleEmitterBase::SetParticleColor1( const std::string & color ) { vector < string > colors = SplitString (color, ';'); if ( colors.size() < 3 ) return; //Color is incorrect SetParticleRed1(ToInt(colors[0])); SetParticleGreen1(ToInt(colors[1])); SetParticleBlue1(ToInt(colors[2])); } void ParticleEmitterBase::SetParticleColor2( const std::string & color ) { vector < string > colors = SplitString (color, ';'); if ( colors.size() < 3 ) return; //Color is incorrect SetParticleRed2(ToInt(colors[0])); SetParticleGreen2(ToInt(colors[1])); SetParticleBlue2(ToInt(colors[2])); } /** * Change the texture */ void ParticleEmitterBase::SetTexture( RuntimeScene & scene, const std::string & textureParticleName_ ) { textureParticleName = textureParticleName_; if ( particleSystem && rendererType == Quad ) { //Load new texture particleSystem->openGLTextureParticle = scene.GetImageManager()->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()); } } } /** * Used by copy constructor and assignment operator. * \warning Do not forget to update me if members were changed! */ void ParticleEmitterBase::Init(const ParticleEmitterBase & other) { if ( particleSystem ) delete particleSystem; if ( other.particleSystem) particleSystem = new ParticleSystemWrapper(*other.particleSystem); else particleSystem = NULL; 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; destroyWhenNoParticles = other.destroyWhenNoParticles; } gd::Object * CreateParticleEmitterObject(std::string name) { return new ParticleEmitterObject(name); } RuntimeObject * CreateRuntimeParticleEmitterObject(RuntimeScene & scene, const gd::Object & object) { return new RuntimeParticleEmitterObject(scene, object); }