summaryrefslogtreecommitdiff
path: root/src/particle/particleemitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/particle/particleemitter.cpp')
-rw-r--r--src/particle/particleemitter.cpp632
1 files changed, 0 insertions, 632 deletions
diff --git a/src/particle/particleemitter.cpp b/src/particle/particleemitter.cpp
deleted file mode 100644
index 642acd851..000000000
--- a/src/particle/particleemitter.cpp
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * The ManaPlus Client
- * Copyright (C) 2006-2009 The Mana World Development Team
- * Copyright (C) 2009-2010 The Mana Developers
- * Copyright (C) 2011-2017 The ManaPlus Developers
- *
- * This file is part of The ManaPlus Client.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
- */
-
-#include "particle/particleemitter.h"
-
-#include "logger.h"
-
-#include "const/resources/map/map.h"
-
-#include "particle/animationparticle.h"
-#include "particle/rotationalparticle.h"
-
-#include "utils/foreach.h"
-
-#include "resources/imageset.h"
-
-#include "resources/dye/dye.h"
-
-#include "resources/image/image.h"
-
-#include "resources/loaders/imageloader.h"
-#include "resources/loaders/imagesetloader.h"
-#include "resources/loaders/subimageloader.h"
-#include "resources/loaders/subimagesetloader.h"
-
-#include "debug.h"
-
-static const float SIN45 = 0.707106781F;
-static const float DEG_RAD_FACTOR = 0.017453293F;
-
-typedef STD_VECTOR<ImageSet*>::const_iterator ImageSetVectorCIter;
-typedef std::list<ParticleEmitter>::const_iterator ParticleEmitterListCIter;
-
-ParticleEmitter::ParticleEmitter(XmlNodeConstPtrConst emitterNode,
- Particle *const target,
- Map *const map, const int rotation,
- const std::string& dyePalettes) :
- mParticleTarget(target),
- mMap(map),
- mOutput(),
- mOutputPause(),
- mParticleImage(nullptr),
- mParticleAnimation("particle animation"),
- mParticleRotation("particle rotation"),
- mParticleAlpha(),
- mDeathEffect(),
- mParticleChildEmitters(),
- mTempSets(),
- mOutputPauseLeft(0),
- mDeathEffectConditions(0),
- mParticleFollow(false)
-{
- // Initializing default values
- mParticlePosX.set(0.0F);
- mParticlePosY.set(0.0F);
- mParticlePosZ.set(0.0F);
- mParticleAngleHorizontal.set(0.0F);
- mParticleAngleVertical.set(0.0F);
- mParticlePower.set(0.0F);
- mParticleGravity.set(0.0F);
- mParticleRandomness.set(0);
- mParticleBounce.set(0.0F);
- mParticleAcceleration.set(0.0F);
- mParticleDieDistance.set(-1.0F);
- mParticleMomentum.set(1.0F);
- mParticleLifetime.set(-1);
- mParticleFadeOut.set(0);
- mParticleFadeIn.set(0);
- mOutput.set(1);
- mOutputPause.set(0);
- mParticleAlpha.set(1.0F);
-
- if (emitterNode == nullptr)
- return;
- for_each_xml_child_node(propertyNode, emitterNode)
- {
- if (xmlNameEqual(propertyNode, "property"))
- {
- const std::string name = XML::getProperty(
- propertyNode, "name", "");
-
- if (name == "position-x")
- {
- mParticlePosX = readParticleEmitterProp(propertyNode, 0.0F);
- }
- else if (name == "position-y")
- {
- mParticlePosY = readParticleEmitterProp(propertyNode, 0.0F);
- mParticlePosY.minVal *= SIN45;
- mParticlePosY.maxVal *= SIN45;
- mParticlePosY.changeAmplitude *= SIN45;
- }
- else if (name == "position-z")
- {
- mParticlePosZ = readParticleEmitterProp(propertyNode, 0.0F);
- mParticlePosZ.minVal *= SIN45;
- mParticlePosZ.maxVal *= SIN45;
- mParticlePosZ.changeAmplitude *= SIN45;
- }
- else if (name == "image")
- {
- std::string image = XML::getProperty(
- propertyNode, "value", "");
- // Don't leak when multiple images are defined
- if (!image.empty() && (mParticleImage == nullptr))
- {
- if (!dyePalettes.empty())
- Dye::instantiate(image, dyePalettes);
- mParticleImage = Loader::getImage(image);
- }
- }
- else if (name == "subimage")
- {
- std::string image = XML::getProperty(
- propertyNode, "value", "");
- // Don't leak when multiple images are defined
- if (!image.empty() && (mParticleImage == nullptr))
- {
- if (!dyePalettes.empty())
- Dye::instantiate(image, dyePalettes);
- Image *img = Loader::getImage(image);
- if (img != nullptr)
- {
- mParticleImage = Loader::getSubImage(img,
- XML::getProperty(propertyNode, "x", 0),
- XML::getProperty(propertyNode, "y", 0),
- XML::getProperty(propertyNode, "width", 0),
- XML::getProperty(propertyNode, "height", 0));
- img->decRef();
- }
- else
- {
- mParticleImage = nullptr;
- }
- }
- }
- else if (name == "horizontal-angle")
- {
- mParticleAngleHorizontal =
- readParticleEmitterProp(propertyNode, 0.0F);
- mParticleAngleHorizontal.minVal
- += static_cast<float>(rotation);
- mParticleAngleHorizontal.minVal *= DEG_RAD_FACTOR;
- mParticleAngleHorizontal.maxVal
- += static_cast<float>(rotation);
- mParticleAngleHorizontal.maxVal *= DEG_RAD_FACTOR;
- mParticleAngleHorizontal.changeAmplitude *= DEG_RAD_FACTOR;
- }
- else if (name == "vertical-angle")
- {
- mParticleAngleVertical =
- readParticleEmitterProp(propertyNode, 0.0F);
- mParticleAngleVertical.minVal *= DEG_RAD_FACTOR;
- mParticleAngleVertical.maxVal *= DEG_RAD_FACTOR;
- mParticleAngleVertical.changeAmplitude *= DEG_RAD_FACTOR;
- }
- else if (name == "power")
- {
- mParticlePower = readParticleEmitterProp(propertyNode, 0.0F);
- }
- else if (name == "gravity")
- {
- mParticleGravity = readParticleEmitterProp(propertyNode, 0.0F);
- }
- else if (name == "randomnes"
- || name == "randomness") // legacy bug
- {
- mParticleRandomness = readParticleEmitterProp(propertyNode, 0);
- }
- else if (name == "bounce")
- {
- mParticleBounce = readParticleEmitterProp(propertyNode, 0.0F);
- }
- else if (name == "lifetime")
- {
- mParticleLifetime = readParticleEmitterProp(propertyNode, 0);
- mParticleLifetime.minVal += 1;
- }
- else if (name == "output")
- {
- mOutput = readParticleEmitterProp(propertyNode, 0);
- mOutput.maxVal += 1;
- }
- else if (name == "output-pause")
- {
- mOutputPause = readParticleEmitterProp(propertyNode, 0);
- mOutputPauseLeft = mOutputPause.value(0);
- }
- else if (name == "acceleration")
- {
- mParticleAcceleration = readParticleEmitterProp(
- propertyNode, 0.0F);
- }
- else if (name == "die-distance")
- {
- mParticleDieDistance = readParticleEmitterProp(
- propertyNode, 0.0F);
- }
- else if (name == "momentum")
- {
- mParticleMomentum = readParticleEmitterProp(
- propertyNode, 1.0F);
- }
- else if (name == "fade-out")
- {
- mParticleFadeOut = readParticleEmitterProp(propertyNode, 0);
- }
- else if (name == "fade-in")
- {
- mParticleFadeIn = readParticleEmitterProp(propertyNode, 0);
- }
- else if (name == "alpha")
- {
- mParticleAlpha = readParticleEmitterProp(propertyNode, 1.0F);
- }
- else if (name == "follow-parent")
- {
- const std::string value = XML::getProperty(propertyNode,
- "value", "0");
- if (value == "1" || value == "true")
- mParticleFollow = true;
- }
- else
- {
- logger->log("Particle Engine: Warning, "
- "unknown emitter property \"%s\"",
- name.c_str());
- }
- }
- else if (xmlNameEqual(propertyNode, "emitter"))
- {
- ParticleEmitter newEmitter(propertyNode, mParticleTarget, map,
- rotation, dyePalettes);
- mParticleChildEmitters.push_back(newEmitter);
- }
- else if (xmlNameEqual(propertyNode, "rotation")
- || xmlNameEqual(propertyNode, "animation"))
- {
- ImageSet *const imageset = getImageSet(propertyNode);
- if (imageset == nullptr)
- {
- logger->log1("Error: no valid imageset");
- continue;
- }
- mTempSets.push_back(imageset);
-
- Animation &animation = (xmlNameEqual(propertyNode, "rotation")) !=
- 0 ? mParticleRotation : mParticleAnimation;
-
- // Get animation frames
- for_each_xml_child_node(frameNode, propertyNode)
- {
- const int delay = XML::getIntProperty(
- frameNode, "delay", 0, 0, 100000);
- const int offsetX = XML::getProperty(frameNode, "offsetX", 0)
- - imageset->getWidth() / 2 + mapTileSize / 2;
- const int offsetY = XML::getProperty(frameNode, "offsetY", 0)
- - imageset->getHeight() + mapTileSize;
- const int rand = XML::getIntProperty(
- frameNode, "rand", 100, 0, 100);
-
- if (xmlNameEqual(frameNode, "frame"))
- {
- const int index = XML::getProperty(frameNode, "index", -1);
-
- if (index < 0)
- {
- logger->log1("No valid value for 'index'");
- continue;
- }
-
- Image *const img = imageset->get(index);
-
- if (img == nullptr)
- {
- logger->log("No image at index %d", index);
- continue;
- }
-
- animation.addFrame(img, delay,
- offsetX, offsetY, rand);
- }
- else if (xmlNameEqual(frameNode, "sequence"))
- {
- int start = XML::getProperty(frameNode, "start", -1);
- const int end = XML::getProperty(frameNode, "end", -1);
-
- if (start < 0 || end < 0)
- {
- logger->log1("No valid value for 'start' or 'end'");
- continue;
- }
-
- while (end >= start)
- {
- Image *const img = imageset->get(start);
- if (img == nullptr)
- {
- logger->log("No image at index %d", start);
- continue;
- }
-
- animation.addFrame(img, delay,
- offsetX, offsetY, rand);
- start ++;
- }
- }
- else if (xmlNameEqual(frameNode, "end"))
- {
- animation.addTerminator(rand);
- }
- } // for frameNode
- }
- else if (xmlNameEqual(propertyNode, "deatheffect"))
- {
- if (!XmlHaveChildContent(propertyNode))
- continue;
- mDeathEffect = XmlChildContent(propertyNode);
- mDeathEffectConditions = 0x00;
- if (XML::getBoolProperty(propertyNode, "on-floor", true))
- {
- mDeathEffectConditions += CAST_S8(
- AliveStatus::DEAD_FLOOR);
- }
- if (XML::getBoolProperty(propertyNode, "on-sky", true))
- {
- mDeathEffectConditions += CAST_S8(
- AliveStatus::DEAD_SKY);
- }
- if (XML::getBoolProperty(propertyNode, "on-other", false))
- {
- mDeathEffectConditions += CAST_S8(
- AliveStatus::DEAD_OTHER);
- }
- if (XML::getBoolProperty(propertyNode, "on-impact", true))
- {
- mDeathEffectConditions += CAST_S8(
- AliveStatus::DEAD_IMPACT);
- }
- if (XML::getBoolProperty(propertyNode, "on-timeout", true))
- {
- mDeathEffectConditions += CAST_S8(
- AliveStatus::DEAD_TIMEOUT);
- }
- }
- }
-}
-
-ParticleEmitter::ParticleEmitter(const ParticleEmitter &o)
-{
- *this = o;
-}
-
-ImageSet *ParticleEmitter::getImageSet(XmlNodePtrConst node)
-{
- ImageSet *imageset = nullptr;
- const int subX = XML::getProperty(node, "subX", -1);
- if (subX != -1)
- {
- Image *const img = Loader::getImage(XML::getProperty(
- node, "imageset", ""));
- if (img == nullptr)
- return nullptr;
-
- Image *const img2 = Loader::getSubImage(img, subX,
- XML::getProperty(node, "subY", 0),
- XML::getProperty(node, "subWidth", 0),
- XML::getProperty(node, "subHeight", 0));
- if (img2 == nullptr)
- {
- img->decRef();
- return nullptr;
- }
-
- imageset = Loader::getSubImageSet(img2,
- XML::getProperty(node, "width", 0),
- XML::getProperty(node, "height", 0));
- img2->decRef();
- img->decRef();
- }
- else
- {
- imageset = Loader::getImageSet(
- XML::getProperty(node, "imageset", ""),
- XML::getProperty(node, "width", 0),
- XML::getProperty(node, "height", 0));
- }
- return imageset;
-}
-
-ParticleEmitter & ParticleEmitter::operator=(const ParticleEmitter &o)
-{
- mParticlePosX = o.mParticlePosX;
- mParticlePosY = o.mParticlePosY;
- mParticlePosZ = o.mParticlePosZ;
- mParticleAngleHorizontal = o.mParticleAngleHorizontal;
- mParticleAngleVertical = o.mParticleAngleVertical;
- mParticlePower = o.mParticlePower;
- mParticleGravity = o.mParticleGravity;
- mParticleRandomness = o.mParticleRandomness;
- mParticleBounce = o.mParticleBounce;
- mParticleFollow = o.mParticleFollow;
- mParticleTarget = o.mParticleTarget;
- mParticleAcceleration = o.mParticleAcceleration;
- mParticleDieDistance = o.mParticleDieDistance;
- mParticleMomentum = o.mParticleMomentum;
- mParticleLifetime = o.mParticleLifetime;
- mParticleFadeOut = o.mParticleFadeOut;
- mParticleFadeIn = o.mParticleFadeIn;
- mParticleAlpha = o.mParticleAlpha;
- mMap = o.mMap;
- mOutput = o.mOutput;
- mOutputPause = o.mOutputPause;
- mParticleImage = o.mParticleImage;
- mParticleAnimation = o.mParticleAnimation;
- mParticleRotation = o.mParticleRotation;
- mParticleChildEmitters = o.mParticleChildEmitters;
- mDeathEffectConditions = o.mDeathEffectConditions;
- mDeathEffect = o.mDeathEffect;
- mTempSets = o.mTempSets;
-
- FOR_EACH (ImageSetVectorCIter, i, mTempSets)
- {
- if (*i != nullptr)
- (*i)->incRef();
- }
-
- mOutputPauseLeft = 0;
-
- if (mParticleImage != nullptr)
- mParticleImage->incRef();
-
- return *this;
-}
-
-ParticleEmitter::~ParticleEmitter()
-{
- FOR_EACH (ImageSetVectorCIter, i, mTempSets)
- {
- if (*i != nullptr)
- (*i)->decRef();
- }
- mTempSets.clear();
-
- if (mParticleImage != nullptr)
- {
- mParticleImage->decRef();
- mParticleImage = nullptr;
- }
-}
-
-template <typename T> ParticleEmitterProp<T>
-ParticleEmitter::readParticleEmitterProp(XmlNodePtrConst propertyNode, T def)
-{
- ParticleEmitterProp<T> retval;
-
- def = static_cast<T>(XML::getDoubleProperty(propertyNode, "value",
- static_cast<double>(def)));
- retval.set(static_cast<T>(XML::getDoubleProperty(propertyNode, "min",
- static_cast<double>(def))), static_cast<T>(XML::getDoubleProperty(
- propertyNode, "max", static_cast<double>(def))));
-
- const std::string change = XML::getProperty(
- propertyNode, "change-func", "none");
- T amplitude = static_cast<T>(XML::getDoubleProperty(propertyNode,
- "change-amplitude", 0.0));
-
- const int period = XML::getProperty(propertyNode, "change-period", 0);
- const int phase = XML::getProperty(propertyNode, "change-phase", 0);
- if (change == "saw" || change == "sawtooth")
- {
- retval.setFunction(ParticleChangeFunc::FUNC_SAW,
- amplitude, period, phase);
- }
- else if (change == "sine" || change == "sinewave")
- {
- retval.setFunction(ParticleChangeFunc::FUNC_SINE,
- amplitude, period, phase);
- }
- else if (change == "triangle")
- {
- retval.setFunction(ParticleChangeFunc::FUNC_TRIANGLE,
- amplitude, period, phase);
- }
- else if (change == "square")
- {
- retval.setFunction(ParticleChangeFunc::FUNC_SQUARE,
- amplitude, period, phase);
- }
-
- return retval;
-}
-
-void ParticleEmitter::createParticles(const int tick,
- STD_VECTOR<Particle*> &newParticles)
-{
- if (mOutputPauseLeft > 0)
- {
- mOutputPauseLeft --;
- return;
- }
- mOutputPauseLeft = mOutputPause.value(tick);
-
- for (int i = mOutput.value(tick); i > 0; i--)
- {
- // Limit maximum particles
- if (ParticleEngine::particleCount > ParticleEngine::maxCount)
- break;
-
- Particle *newParticle = nullptr;
- if (mParticleImage != nullptr)
- {
- const std::string &name = mParticleImage->mIdPath;
- if (ImageParticle::imageParticleCountByName.find(name) ==
- ImageParticle::imageParticleCountByName.end())
- {
- ImageParticle::imageParticleCountByName[name] = 0;
- }
-
- if (ImageParticle::imageParticleCountByName[name] > 200)
- break;
-
- newParticle = new ImageParticle(mParticleImage);
- newParticle->setMap(mMap);
- }
- else if (!mParticleRotation.mFrames.empty())
- {
- Animation *const newAnimation = new Animation(mParticleRotation);
- newParticle = new RotationalParticle(newAnimation);
- newParticle->setMap(mMap);
- }
- else if (!mParticleAnimation.mFrames.empty())
- {
- Animation *const newAnimation = new Animation(mParticleAnimation);
- newParticle = new AnimationParticle(newAnimation);
- newParticle->setMap(mMap);
- }
- else
- {
- newParticle = new Particle;
- newParticle->setMap(mMap);
- }
-
- const Vector position(mParticlePosX.value(tick),
- mParticlePosY.value(tick),
- mParticlePosZ.value(tick));
- newParticle->moveTo(position);
-
- const float angleH = mParticleAngleHorizontal.value(tick);
- const float cosAngleH = static_cast<float>(cos(angleH));
- const float sinAngleH = static_cast<float>(sin(angleH));
- const float angleV = mParticleAngleVertical.value(tick);
- const float cosAngleV = static_cast<float>(cos(angleV));
- const float sinAngleV = static_cast<float>(sin(angleV));
- const float power = mParticlePower.value(tick);
- newParticle->setVelocity(cosAngleH * cosAngleV * power,
- sinAngleH * cosAngleV * power,
- sinAngleV * power);
-
- newParticle->setRandomness(mParticleRandomness.value(tick));
- newParticle->setGravity(mParticleGravity.value(tick));
- newParticle->setBounce(mParticleBounce.value(tick));
- newParticle->setFollow(mParticleFollow);
-
- newParticle->setDestination(mParticleTarget,
- mParticleAcceleration.value(tick),
- mParticleMomentum.value(tick));
-
- newParticle->setDieDistance(mParticleDieDistance.value(tick));
-
- newParticle->setLifetime(mParticleLifetime.value(tick));
- newParticle->setFadeOut(mParticleFadeOut.value(tick));
- newParticle->setFadeIn(mParticleFadeIn.value(tick));
- newParticle->setAlpha(mParticleAlpha.value(tick));
-
- FOR_EACH (ParticleEmitterListCIter, it, mParticleChildEmitters)
- newParticle->addEmitter(new ParticleEmitter(*it));
-
- if (!mDeathEffect.empty())
- newParticle->setDeathEffect(mDeathEffect, mDeathEffectConditions);
-
- newParticles.push_back(newParticle);
- }
-}
-
-void ParticleEmitter::adjustSize(const int w, const int h)
-{
- if (w == 0 || h == 0)
- return; // new dimensions are illegal
-
- // calculate the old rectangle
- const int oldArea = CAST_S32(
- mParticlePosX.maxVal - mParticlePosX.minVal) * CAST_S32(
- mParticlePosX.maxVal - mParticlePosY.minVal);
- if (oldArea == 0)
- {
- // when the effect has no dimension it is
- // not designed to be resizeable
- return;
- }
-
- // set the new dimensions
- mParticlePosX.set(0, static_cast<float>(w));
- mParticlePosY.set(0, static_cast<float>(h));
- const int newArea = w * h;
- // adjust the output so that the particle density stays the same
- const float outputFactor = static_cast<float>(newArea)
- / static_cast<float>(oldArea);
- mOutput.minVal = CAST_S32(static_cast<float>(
- mOutput.minVal) * outputFactor);
- mOutput.maxVal = CAST_S32(static_cast<float>(
- mOutput.maxVal) * outputFactor);
-}