2010-03-27 04:09:11 +01:00
|
|
|
// ==============================================================
|
|
|
|
// This file is part of Glest (www.glest.org)
|
|
|
|
//
|
2011-12-14 08:40:48 +01:00
|
|
|
// Copyright (C) 2001-2008 Martiño Figueroa
|
2010-03-27 04:09:11 +01:00
|
|
|
//
|
|
|
|
// You can redistribute this code 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 (at your option) any later version
|
|
|
|
// ==============================================================
|
|
|
|
|
|
|
|
#include "unit_particle_type.h"
|
|
|
|
|
|
|
|
#include "util.h"
|
|
|
|
#include "core_data.h"
|
|
|
|
#include "xml_parser.h"
|
|
|
|
#include "config.h"
|
|
|
|
#include "game_constants.h"
|
2011-07-07 00:23:51 +02:00
|
|
|
#include "platform_common.h"
|
2012-03-10 04:27:25 +01:00
|
|
|
#include "conversion.h"
|
2010-03-27 04:09:11 +01:00
|
|
|
#include "leak_dumper.h"
|
|
|
|
|
|
|
|
using namespace Shared::Xml;
|
|
|
|
using namespace Shared::Graphics;
|
2010-10-06 22:22:06 +02:00
|
|
|
using namespace Shared::Util;
|
2011-07-07 00:23:51 +02:00
|
|
|
using namespace Shared::PlatformCommon;
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
namespace Glest{ namespace Game{
|
|
|
|
|
|
|
|
// =====================================================
|
|
|
|
// class UnitParticleSystemType
|
|
|
|
// =====================================================
|
2011-08-27 08:52:17 +02:00
|
|
|
UnitParticleSystemType::UnitParticleSystemType() : ParticleSystemType() {
|
|
|
|
shape = UnitParticleSystem::sLinear;
|
|
|
|
angle = 0;
|
|
|
|
radius = 0;
|
|
|
|
minRadius = 0;
|
|
|
|
emissionRateFade = 0;
|
|
|
|
relative = false;
|
|
|
|
relativeDirection = false;
|
|
|
|
fixed = false;
|
|
|
|
staticParticleCount = 0;
|
2012-01-07 21:24:54 +01:00
|
|
|
isVisibleAtNight = true;
|
|
|
|
isVisibleAtDay = true;
|
|
|
|
isDaylightAffected = false;
|
2011-08-27 08:52:17 +02:00
|
|
|
radiusBasedStartenergy = false;
|
|
|
|
delay = 0;
|
|
|
|
lifetime = 0;
|
|
|
|
startTime = 0;
|
|
|
|
endTime = 1;
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
|
2011-03-15 16:30:28 +01:00
|
|
|
void UnitParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir,
|
2011-05-06 09:47:31 +02:00
|
|
|
RendererInterface *renderer, std::map<string,vector<pair<string, string> > > &loadedFileList,
|
2011-05-07 00:12:16 +02:00
|
|
|
string parentLoader, string techtreePath) {
|
2011-07-07 00:23:51 +02:00
|
|
|
|
2011-05-07 00:12:16 +02:00
|
|
|
ParticleSystemType::load(particleSystemNode, dir, renderer, loadedFileList,
|
|
|
|
parentLoader,techtreePath);
|
2011-07-07 00:23:51 +02:00
|
|
|
|
|
|
|
//shape
|
|
|
|
angle= 0.0f;
|
|
|
|
if(particleSystemNode->hasChild("shape")){
|
|
|
|
const XmlNode *shapeNode= particleSystemNode->getChild("shape");
|
|
|
|
shape= UnitParticleSystem::strToShape(shapeNode->getAttribute("value")->getRestrictedValue());
|
|
|
|
if(shape == UnitParticleSystem::sConical){
|
|
|
|
angle= shapeNode->getChild("angle")->getAttribute("value")->getFloatValue();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
shape = UnitParticleSystem::sLinear;
|
|
|
|
}
|
|
|
|
if(shape != UnitParticleSystem::sSpherical){
|
|
|
|
//direction
|
|
|
|
const XmlNode *directionNode= particleSystemNode->getChild("direction");
|
|
|
|
direction.x= directionNode->getAttribute("x")->getFloatValue();
|
|
|
|
direction.y= directionNode->getAttribute("y")->getFloatValue();
|
|
|
|
direction.z= directionNode->getAttribute("z")->getFloatValue();
|
|
|
|
if((shape == UnitParticleSystem::sConical) && (0.0 == direction.length()))
|
2012-04-14 23:21:09 +02:00
|
|
|
throw megaglest_runtime_error("direction cannot be zero");
|
2011-07-07 00:23:51 +02:00
|
|
|
// ought to warn about 0 directions generally
|
|
|
|
}
|
|
|
|
|
|
|
|
//emission rate fade
|
|
|
|
if(particleSystemNode->hasChild("emission-rate-fade")){
|
|
|
|
const XmlNode *emissionRateFadeNode= particleSystemNode->getChild("emission-rate-fade");
|
|
|
|
emissionRateFade= emissionRateFadeNode->getAttribute("value")->getFloatValue();
|
|
|
|
} else {
|
|
|
|
emissionRateFade = 0;
|
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//radius
|
|
|
|
const XmlNode *radiusNode= particleSystemNode->getChild("radius");
|
|
|
|
radius= radiusNode->getAttribute("value")->getFloatValue();
|
2011-07-07 00:23:51 +02:00
|
|
|
|
|
|
|
// min radius
|
|
|
|
if(particleSystemNode->hasChild("min-radius")){
|
|
|
|
const XmlNode *minRadiusNode= particleSystemNode->getChild("min-radius");
|
|
|
|
minRadius= minRadiusNode->getAttribute("value")->getFloatValue();
|
|
|
|
if(minRadius > radius)
|
2012-04-14 23:21:09 +02:00
|
|
|
throw megaglest_runtime_error("min-radius cannot be bigger than radius");
|
2011-07-07 00:23:51 +02:00
|
|
|
} else {
|
|
|
|
minRadius = 0;
|
|
|
|
}
|
|
|
|
if((minRadius == 0) && (shape == UnitParticleSystem::sConical)) {
|
2012-04-04 17:36:09 +02:00
|
|
|
minRadius = 0.001f; // fudge it so we aren't generating particles that are exactly centred
|
2011-07-07 00:23:51 +02:00
|
|
|
if(minRadius > radius)
|
|
|
|
radius = minRadius;
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
//relative
|
|
|
|
const XmlNode *relativeNode= particleSystemNode->getChild("relative");
|
|
|
|
relative= relativeNode->getAttribute("value")->getBoolValue();
|
|
|
|
|
2011-03-02 00:36:33 +01:00
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
//relativeDirection
|
|
|
|
if(particleSystemNode->hasChild("relativeDirection")){
|
|
|
|
const XmlNode *relativeDirectionNode= particleSystemNode->getChild("relativeDirection");
|
|
|
|
relativeDirection= relativeDirectionNode->getAttribute("value")->getBoolValue();
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
relativeDirection=true;
|
|
|
|
}
|
|
|
|
|
2010-09-25 16:38:00 +02:00
|
|
|
if(particleSystemNode->hasChild("static-particle-count")){
|
|
|
|
//staticParticleCount
|
|
|
|
const XmlNode *staticParticleCountNode= particleSystemNode->getChild("static-particle-count");
|
|
|
|
staticParticleCount= staticParticleCountNode->getAttribute("value")->getIntValue();
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
staticParticleCount=0;
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
//isVisibleAtNight
|
|
|
|
if(particleSystemNode->hasChild("isVisibleAtNight")){
|
|
|
|
const XmlNode *isVisibleAtNightNode= particleSystemNode->getChild("isVisibleAtNight");
|
|
|
|
isVisibleAtNight= isVisibleAtNightNode->getAttribute("value")->getBoolValue();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
isVisibleAtNight=true;
|
|
|
|
}
|
|
|
|
|
|
|
|
//isVisibleAtDay
|
|
|
|
if(particleSystemNode->hasChild("isVisibleAtDay")){
|
|
|
|
const XmlNode *isVisibleAtDayNode= particleSystemNode->getChild("isVisibleAtDay");
|
|
|
|
isVisibleAtDay= isVisibleAtDayNode->getAttribute("value")->getBoolValue();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
isVisibleAtDay=true;
|
|
|
|
}
|
|
|
|
|
2012-01-07 21:24:54 +01:00
|
|
|
//isDaylightAffected
|
|
|
|
if(particleSystemNode->hasChild("isDaylightAffected")){
|
|
|
|
const XmlNode *node= particleSystemNode->getChild("isDaylightAffected");
|
|
|
|
isDaylightAffected= node->getAttribute("value")->getBoolValue();
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
isDaylightAffected=false;
|
|
|
|
}
|
|
|
|
|
2011-03-14 00:16:07 +01:00
|
|
|
//radiusBasedStartenergy
|
|
|
|
if(particleSystemNode->hasChild("radiusBasedStartenergy")){
|
|
|
|
const XmlNode *isVisibleAtDayNode= particleSystemNode->getChild("radiusBasedStartenergy");
|
|
|
|
radiusBasedStartenergy= isVisibleAtDayNode->getAttribute("value")->getBoolValue();
|
|
|
|
}
|
|
|
|
else{
|
|
|
|
radiusBasedStartenergy= true;
|
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
//fixed
|
|
|
|
const XmlNode *fixedNode= particleSystemNode->getChild("fixed");
|
|
|
|
fixed= fixedNode->getAttribute("value")->getBoolValue();
|
|
|
|
|
|
|
|
// delay
|
|
|
|
if(particleSystemNode->hasChild("delay")) {
|
|
|
|
const XmlNode* delayNode = particleSystemNode->getChild("delay");
|
2013-10-02 22:22:10 +02:00
|
|
|
const float delay_secs = delayNode->getAttribute("value")->getFloatValue();
|
2011-07-07 00:23:51 +02:00
|
|
|
if(delay_secs < 0)
|
2012-04-14 23:21:09 +02:00
|
|
|
throw megaglest_runtime_error("particle effect delay cannot be negative");
|
2012-04-04 17:36:09 +02:00
|
|
|
delay = (int)delay_secs * GameConstants::updateFps;
|
2011-07-07 00:23:51 +02:00
|
|
|
} else{
|
|
|
|
delay= 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
// lifetime
|
|
|
|
if(particleSystemNode->hasChild("lifetime")) {
|
|
|
|
const XmlNode* lifetimeNode = particleSystemNode->getChild("lifetime");
|
2013-10-02 22:22:10 +02:00
|
|
|
const float lifetime_secs = lifetimeNode->getAttribute("value")->getFloatValue();
|
2011-07-07 00:23:51 +02:00
|
|
|
if(lifetime_secs < 0 && lifetime_secs != -1)
|
2012-04-14 23:21:09 +02:00
|
|
|
throw megaglest_runtime_error("particle effect lifetime cannot be negative (-1 means inherited from parent particle)");
|
2012-04-04 17:36:09 +02:00
|
|
|
lifetime = (int)lifetime_secs * GameConstants::updateFps;
|
2011-07-07 00:23:51 +02:00
|
|
|
} else{
|
|
|
|
lifetime= -1; //default
|
|
|
|
}
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2012-05-24 09:08:31 +02:00
|
|
|
ObjectParticleSystemType::ObjectParticleSystemType() : UnitParticleSystemType() {
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) printf("In [%s Line: %d] NEW [%p]\n",__FUNCTION__,__LINE__,this);
|
|
|
|
}
|
|
|
|
ObjectParticleSystemType::~ObjectParticleSystemType() {
|
|
|
|
if(SystemFlags::VERBOSE_MODE_ENABLED) {
|
|
|
|
printf("In [%s Line: %d] NEW [%p]\n",__FUNCTION__,__LINE__,this);
|
2012-07-18 16:31:56 +02:00
|
|
|
//printf("%s\n",PlatformExceptionHandler::getStackTrace().c_str());
|
2012-05-24 09:08:31 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-03-09 02:32:27 +01:00
|
|
|
const void UnitParticleSystemType::setValues(UnitParticleSystem *ups){
|
2011-07-07 00:23:51 +02:00
|
|
|
// whilst we extend ParticleSystemType we don't use ParticleSystemType::setValues()
|
|
|
|
// add instances of all children; some settings will cascade to all children
|
2011-09-01 01:10:43 +02:00
|
|
|
for(Children::iterator i=children.begin(); i!=children.end(); ++i){
|
2011-07-07 00:23:51 +02:00
|
|
|
UnitParticleSystem *child = new UnitParticleSystem();
|
2013-09-23 19:16:34 +02:00
|
|
|
child->setParticleOwner(ups->getParticleOwner());
|
2011-07-07 00:23:51 +02:00
|
|
|
(*i)->setValues(child);
|
|
|
|
ups->addChild(child);
|
|
|
|
}
|
|
|
|
// set values
|
|
|
|
ups->setModel(model);
|
|
|
|
ups->setModelCycle(modelCycle);
|
2010-03-27 04:09:11 +01:00
|
|
|
ups->setTexture(texture);
|
|
|
|
ups->setPrimitive(UnitParticleSystem::strToPrimitive(primitive));
|
|
|
|
ups->setOffset(offset);
|
2011-07-07 00:23:51 +02:00
|
|
|
ups->setShape(shape);
|
|
|
|
ups->setAngle(angle);
|
2010-03-27 04:09:11 +01:00
|
|
|
ups->setDirection(direction);
|
|
|
|
ups->setColor(color);
|
|
|
|
ups->setColorNoEnergy(colorNoEnergy);
|
|
|
|
ups->setSpeed(speed);
|
|
|
|
ups->setGravity(gravity);
|
|
|
|
ups->setParticleSize(size);
|
|
|
|
ups->setSizeNoEnergy(sizeNoEnergy);
|
|
|
|
ups->setEmissionRate(emissionRate);
|
|
|
|
ups->setMaxParticleEnergy(energyMax);
|
|
|
|
ups->setVarParticleEnergy(energyVar);
|
|
|
|
ups->setFixed(fixed);
|
|
|
|
ups->setRelative(relative);
|
|
|
|
ups->setRelativeDirection(relativeDirection);
|
2011-07-07 00:23:51 +02:00
|
|
|
ups->setDelay(delay);
|
|
|
|
ups->setLifetime(lifetime);
|
|
|
|
ups->setEmissionRateFade(emissionRateFade);
|
2010-03-27 04:09:11 +01:00
|
|
|
ups->setTeamcolorNoEnergy(teamcolorNoEnergy);
|
|
|
|
ups->setTeamcolorEnergy(teamcolorEnergy);
|
2011-03-14 00:16:07 +01:00
|
|
|
ups->setAlternations(alternations);
|
2012-01-07 21:24:54 +01:00
|
|
|
ups->setParticleSystemStartDelay(particleSystemStartDelay);
|
2011-03-14 00:16:07 +01:00
|
|
|
|
|
|
|
ups->setIsVisibleAtNight(isVisibleAtNight);
|
|
|
|
ups->setIsVisibleAtDay(isVisibleAtDay);
|
2012-01-07 21:24:54 +01:00
|
|
|
ups->setIsDaylightAffected(isDaylightAffected);
|
2010-09-25 16:38:00 +02:00
|
|
|
ups->setStaticParticleCount(staticParticleCount);
|
2010-03-27 04:09:11 +01:00
|
|
|
ups->setRadius(radius);
|
2011-07-07 00:23:51 +02:00
|
|
|
ups->setMinRadius(minRadius);
|
2010-03-27 04:09:11 +01:00
|
|
|
ups->setBlendMode(ParticleSystem::strToBlendMode(mode));
|
2011-03-14 00:16:07 +01:00
|
|
|
ups->setRadiusBasedStartenergy(radiusBasedStartenergy);
|
2010-09-25 16:38:00 +02:00
|
|
|
//prepare system for given staticParticleCount
|
|
|
|
if(staticParticleCount>0)
|
|
|
|
{
|
|
|
|
ups->setEmissionRate(0.0f);
|
|
|
|
ups->setSpeed(0);
|
|
|
|
direction.x= 0.0f;
|
|
|
|
direction.y= 0.0f;
|
|
|
|
direction.z= 0.0f;
|
|
|
|
ups->setDirection(direction);
|
|
|
|
}
|
2011-08-27 08:52:17 +02:00
|
|
|
|
|
|
|
ups->setStartTime(startTime);
|
|
|
|
ups->setEndTime(endTime);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
void UnitParticleSystemType::load(const XmlNode *particleFileNode, const string &dir, const string &path,
|
2011-05-06 09:47:31 +02:00
|
|
|
RendererInterface *renderer, std::map<string,vector<pair<string, string> > > &loadedFileList,
|
2011-05-07 00:12:16 +02:00
|
|
|
string parentLoader, string techtreePath) {
|
2010-03-27 04:09:11 +01:00
|
|
|
|
|
|
|
try{
|
|
|
|
XmlTree xmlTree;
|
2011-05-07 00:12:16 +02:00
|
|
|
|
|
|
|
std::map<string,string> mapExtraTagReplacementValues;
|
|
|
|
mapExtraTagReplacementValues["$COMMONDATAPATH"] = techtreePath + "/commondata/";
|
|
|
|
xmlTree.load(path, Properties::getTagReplacementValues(&mapExtraTagReplacementValues));
|
2011-05-06 09:47:31 +02:00
|
|
|
loadedFileList[path].push_back(make_pair(parentLoader,parentLoader));
|
2010-03-27 04:09:11 +01:00
|
|
|
const XmlNode *particleSystemNode= xmlTree.getRootNode();
|
|
|
|
|
2011-07-07 00:23:51 +02:00
|
|
|
if(particleFileNode){
|
|
|
|
// immediate children in the particleFileNode will override the particleSystemNode
|
|
|
|
particleFileNode->setSuper(particleSystemNode);
|
|
|
|
particleSystemNode= particleFileNode;
|
|
|
|
}
|
|
|
|
|
2011-03-15 16:30:28 +01:00
|
|
|
UnitParticleSystemType::load(particleSystemNode, dir, renderer,
|
2011-05-07 00:12:16 +02:00
|
|
|
loadedFileList, parentLoader, techtreePath);
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
catch(const exception &e){
|
2010-10-06 22:22:06 +02:00
|
|
|
SystemFlags::OutputDebug(SystemFlags::debugError,"In [%s::%s Line: %d] Error [%s]\n",__FILE__,__FUNCTION__,__LINE__,e.what());
|
2012-04-14 23:21:09 +02:00
|
|
|
throw megaglest_runtime_error("Error loading ParticleSystem: "+ path + "\n" +e.what());
|
2010-03-27 04:09:11 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-03-10 04:27:25 +01:00
|
|
|
void UnitParticleSystemType::saveGame(XmlNode *rootNode) {
|
|
|
|
ParticleSystemType::saveGame(rootNode);
|
|
|
|
|
|
|
|
std::map<string,string> mapTagReplacements;
|
|
|
|
XmlNode *unitParticleSystemTypeNode = rootNode->addChild("UnitParticleSystemType");
|
|
|
|
|
|
|
|
// UnitParticleSystem::Shape shape;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("shape",intToStr(shape), mapTagReplacements);
|
|
|
|
// float angle;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("angle",floatToStr(angle,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
// float radius;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("radius",floatToStr(radius,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
// float minRadius;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("minRadius",floatToStr(minRadius,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
// float emissionRateFade;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("emissionRateFade",floatToStr(emissionRateFade,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
// Vec3f direction;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("direction",direction.getString(), mapTagReplacements);
|
|
|
|
// bool relative;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("relative",intToStr(relative), mapTagReplacements);
|
|
|
|
// bool relativeDirection;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("relativeDirection",intToStr(relativeDirection), mapTagReplacements);
|
|
|
|
// bool fixed;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("fixed",intToStr(fixed), mapTagReplacements);
|
|
|
|
// int staticParticleCount;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("staticParticleCount",intToStr(staticParticleCount), mapTagReplacements);
|
|
|
|
// bool isVisibleAtNight;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("isVisibleAtNight",intToStr(isVisibleAtNight), mapTagReplacements);
|
|
|
|
// bool isVisibleAtDay;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("isVisibleAtDay",intToStr(isVisibleAtDay), mapTagReplacements);
|
|
|
|
// bool isDaylightAffected;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("isDaylightAffected",intToStr(isDaylightAffected), mapTagReplacements);
|
|
|
|
// bool radiusBasedStartenergy;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("radiusBasedStartenergy",intToStr(radiusBasedStartenergy), mapTagReplacements);
|
|
|
|
// int delay;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("delay",intToStr(delay), mapTagReplacements);
|
|
|
|
// int lifetime;
|
|
|
|
unitParticleSystemTypeNode->addAttribute("lifetime",intToStr(lifetime), mapTagReplacements);
|
|
|
|
// float startTime;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("startTime",floatToStr(startTime,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
// float endTime;
|
2013-10-02 22:22:10 +02:00
|
|
|
unitParticleSystemTypeNode->addAttribute("endTime",floatToStr(endTime,6), mapTagReplacements);
|
2012-03-10 04:27:25 +01:00
|
|
|
}
|
|
|
|
|
2010-03-27 04:09:11 +01:00
|
|
|
}}//end mamespace
|