diff --git a/source/glest_game/graphics/particle_type.h b/source/glest_game/graphics/particle_type.h index ba6dc421..b8382275 100644 --- a/source/glest_game/graphics/particle_type.h +++ b/source/glest_game/graphics/particle_type.h @@ -103,6 +103,8 @@ public: void setMaxHp(int value) { maxHp=value;} void setMinmaxIsPercent(bool value) { minmaxIsPercent=value; } + string getType() const { return type; }; + protected: }; diff --git a/source/glest_game/graphics/unit_particle_type.cpp b/source/glest_game/graphics/unit_particle_type.cpp index be10ad89..9ff4b40e 100644 --- a/source/glest_game/graphics/unit_particle_type.cpp +++ b/source/glest_game/graphics/unit_particle_type.cpp @@ -30,6 +30,24 @@ namespace Glest{ namespace Game{ // ===================================================== // class UnitParticleSystemType // ===================================================== +UnitParticleSystemType::UnitParticleSystemType() : ParticleSystemType() { + shape = UnitParticleSystem::sLinear; + angle = 0; + radius = 0; + minRadius = 0; + emissionRateFade = 0; + relative = false; + relativeDirection = false; + fixed = false; + staticParticleCount = 0; + isVisibleAtNight = false; + isVisibleAtDay = false; + radiusBasedStartenergy = false; + delay = 0; + lifetime = 0; + startTime = 0; + endTime = 1; +} void UnitParticleSystemType::load(const XmlNode *particleSystemNode, const string &dir, RendererInterface *renderer, std::map > > &loadedFileList, @@ -217,6 +235,9 @@ const void UnitParticleSystemType::setValues(UnitParticleSystem *ups){ direction.z= 0.0f; ups->setDirection(direction); } + + ups->setStartTime(startTime); + ups->setEndTime(endTime); } void UnitParticleSystemType::load(const XmlNode *particleFileNode, const string &dir, const string &path, diff --git a/source/glest_game/graphics/unit_particle_type.h b/source/glest_game/graphics/unit_particle_type.h index a90ae6dc..628e792e 100644 --- a/source/glest_game/graphics/unit_particle_type.h +++ b/source/glest_game/graphics/unit_particle_type.h @@ -61,14 +61,24 @@ protected: bool radiusBasedStartenergy; int delay; int lifetime; + float startTime; + float endTime; public: + UnitParticleSystemType(); + void load(const XmlNode *particleSystemNode, const string &dir, RendererInterface *newTexture, std::map > > &loadedFileList, string parentLoader, string techtreePath); void load(const XmlNode *particleFileNode, const string &dir, const string &path, RendererInterface *newTexture, std::map > > &loadedFileList,string parentLoader, string techtreePath); + + void setStartTime(float startTime) { this->startTime = startTime; } + float getStartTime() const { return this->startTime; } + void setEndTime(float endTime) { this->endTime = endTime; } + float getEndTime() const { return this->endTime; } + const void setValues (UnitParticleSystem *uts); bool hasTexture() const { return(texture != NULL); } }; diff --git a/source/glest_game/type_instances/unit.cpp b/source/glest_game/type_instances/unit.cpp index a83bf8ee..f38996e6 100644 --- a/source/glest_game/type_instances/unit.cpp +++ b/source/glest_game/type_instances/unit.cpp @@ -382,6 +382,7 @@ Unit::~Unit() { } // fade(and by this remove) all unit particle systems + queuedUnitParticleSystemTypes.clear(); while(unitParticleSystems.empty() == false) { unitParticleSystems.back()->fade(); unitParticleSystems.pop_back(); @@ -753,10 +754,12 @@ void Unit::setCurrSkill(const SkillType *currSkill) { throw runtime_error(szBuf); } - if(currSkill->getClass() != this->currSkill->getClass()) { + if(currSkill->getClass() != this->currSkill->getClass() || + currSkill->getName() != this->currSkill->getName()) { animProgress= 0; lastAnimProgress= 0; + queuedUnitParticleSystemTypes.clear(); while(unitParticleSystems.empty() == false) { unitParticleSystems.back()->fade(); unitParticleSystems.pop_back(); @@ -764,13 +767,24 @@ void Unit::setCurrSkill(const SkillType *currSkill) { } if(showUnitParticles && (currSkill->unitParticleSystemTypes.empty() == false) && (unitParticleSystems.empty() == true) ) { + //printf("START - particle system type\n"); + for(UnitParticleSystemTypes::const_iterator it= currSkill->unitParticleSystemTypes.begin(); it != currSkill->unitParticleSystemTypes.end(); ++it) { - UnitParticleSystem *ups = new UnitParticleSystem(200); - (*it)->setValues(ups); - ups->setPos(getCurrVector()); - ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); - unitParticleSystems.push_back(ups); - Renderer::getInstance().manageParticleSystem(ups, rsGame); + if((*it)->getStartTime() == 0.0) { + //printf("Adding NON-queued particle system type [%s] [%f] [%f]\n",(*it)->getType().c_str(),(*it)->getStartTime(),(*it)->getEndTime()); + + UnitParticleSystem *ups = new UnitParticleSystem(200); + (*it)->setValues(ups); + ups->setPos(getCurrVector()); + ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + unitParticleSystems.push_back(ups); + Renderer::getInstance().manageParticleSystem(ups, rsGame); + } + else { + //printf("Adding queued particle system type [%s] [%f] [%f]\n",(*it)->getType().c_str(),(*it)->getStartTime(),(*it)->getEndTime()); + + queuedUnitParticleSystemTypes.push_back(*it); + } } } progress2= 0; @@ -1398,6 +1412,50 @@ bool Unit::needToUpdate() { return return_value; } +void Unit::updateTimedParticles() { + //!!! + // Start new particle systems based on start time + for(int i = queuedUnitParticleSystemTypes.size() - 1; i >= 0; i--) { + UnitParticleSystemType *pst = queuedUnitParticleSystemTypes[i]; + if(pst != NULL) { + if(truncateDecimal(pst->getStartTime()) <= truncateDecimal(animProgress)) { + //printf("STARTING queued particle system type [%s] [%f] [%f] [%f] [%f]\n",pst->getType().c_str(),truncateDecimal(pst->getStartTime()),truncateDecimal(pst->getEndTime()),truncateDecimal(animProgress),truncateDecimal(lastAnimProgress)); + + UnitParticleSystem *ups = new UnitParticleSystem(200); + pst->setValues(ups); + ups->setPos(getCurrVector()); + ups->setFactionColor(getFaction()->getTexture()->getPixmapConst()->getPixel3f(0,0)); + unitParticleSystems.push_back(ups); + Renderer::getInstance().manageParticleSystem(ups, rsGame); + + queuedUnitParticleSystemTypes.erase(queuedUnitParticleSystemTypes.begin() + i); + } + } + else { + queuedUnitParticleSystemTypes.erase(queuedUnitParticleSystemTypes.begin() + i); + } + } + + // End existing systems based on end time + for(int i = unitParticleSystems.size() - 1; i >= 0; i--) { + UnitParticleSystem *ps = unitParticleSystems[i]; + if(ps != NULL) { + if(truncateDecimal(ps->getStartTime()) != 0.0 || truncateDecimal(ps->getEndTime()) != 1.0) { + //printf("Checking for end particle system #%d [%d] [%f] [%f] [%f] [%f]\n",i,ps->shape,truncateDecimal(ps->getStartTime()),truncateDecimal(ps->getEndTime()),truncateDecimal(animProgress),truncateDecimal(lastAnimProgress)); + + if(truncateDecimal(animProgress) >= 0.99 || + truncateDecimal(animProgress) >= truncateDecimal(ps->getEndTime())) { + //printf("ENDING particle system [%d]\n",ps->shape); + + ps->fade(); + unitParticleSystems.erase(unitParticleSystems.begin() + i); + } + } + } + } + +} + bool Unit::update() { assert(progress <= 1.f); diff --git a/source/glest_game/type_instances/unit.h b/source/glest_game/type_instances/unit.h index d4d6082f..5923923b 100644 --- a/source/glest_game/type_instances/unit.h +++ b/source/glest_game/type_instances/unit.h @@ -330,6 +330,8 @@ private: Commands commands; Observers observers; vector unitParticleSystems; + vector queuedUnitParticleSystemTypes; + UnitParticleSystems damageParticleSystems; std::map damageParticleSystemsInUse; @@ -579,6 +581,7 @@ public: bool getUsePathfinderExtendedMaxNodes() const { return usePathfinderExtendedMaxNodes; } void setUsePathfinderExtendedMaxNodes(bool value) { usePathfinderExtendedMaxNodes = value; } + void updateTimedParticles(); private: float computeHeight(const Vec2i &pos) const; void calculateXZRotation(); diff --git a/source/glest_game/types/skill_type.cpp b/source/glest_game/types/skill_type.cpp index 208e3d27..54fdd0e0 100644 --- a/source/glest_game/types/skill_type.cpp +++ b/source/glest_game/types/skill_type.cpp @@ -226,6 +226,16 @@ void SkillType::load(const XmlNode *sn, const string &dir, const TechTree *tt, UnitParticleSystemType *unitParticleSystemType= new UnitParticleSystemType(); unitParticleSystemType->load(particleFileNode, dir, currentPath + path, &Renderer::getInstance(), loadedFileList,parentLoader,tt->getPath()); + + if(particleNode->getAttribute("start-time",false) != NULL) { + //printf("*NOTE particle system type has start-time [%f]\n",particleNode->getAttribute("start-time")->getFloatValue()); + unitParticleSystemType->setStartTime(particleNode->getAttribute("start-time")->getFloatValue()); + } + if(particleNode->getAttribute("end-time",false) != NULL) { + //printf("*NOTE particle system type has end-time [%f]\n",particleNode->getAttribute("end-time")->getFloatValue()); + unitParticleSystemType->setEndTime(particleNode->getAttribute("end-time")->getFloatValue()); + } + loadedFileList[currentPath + path].push_back(make_pair(parentLoader,particleFileNode->getAttribute("path")->getRestrictedValue())); unitParticleSystemTypes.push_back(unitParticleSystemType); } diff --git a/source/glest_game/world/unit_updater.cpp b/source/glest_game/world/unit_updater.cpp index 1625d22b..ad11528f 100644 --- a/source/glest_game/world/unit_updater.cpp +++ b/source/glest_game/world/unit_updater.cpp @@ -133,6 +133,10 @@ void UnitUpdater::updateUnit(Unit *unit) { if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after playsound]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + unit->updateTimedParticles(); + + if(SystemFlags::getSystemSettingType(SystemFlags::debugPerformance).enabled && chrono.getMillis() > 0) SystemFlags::OutputDebug(SystemFlags::debugPerformance,"In [%s::%s] Line: %d took msecs: %lld [after playsound]\n",__FILE__,__FUNCTION__,__LINE__,chrono.getMillis()); + //start attack particle system if(unit->getCurrSkill()->getClass() == scAttack) { const AttackSkillType *ast= static_cast(unit->getCurrSkill()); diff --git a/source/shared_lib/include/graphics/math_util.h b/source/shared_lib/include/graphics/math_util.h index cdc563c9..ed89864c 100644 --- a/source/shared_lib/include/graphics/math_util.h +++ b/source/shared_lib/include/graphics/math_util.h @@ -12,6 +12,7 @@ #ifndef _SHARED_GRAPHICS_MATHUTIL_H_ #define _SHARED_GRAPHICS_MATHUTIL_H_ +#include "math_wrapper.h" #include "vec.h" #include "leak_dumper.h" @@ -266,6 +267,21 @@ inline T radToDeg(T rad){ return (rad*360)/(2*pi); } +template +inline T truncateDecimal(const T &value, int precision=6) { + int iSigned = value >= 0 ? 1: -1; + +#ifdef USE_STREFLOP + unsigned int uiTemp = (value * streflop::pow((streflop::Simple)10, (streflop::Simple)precision)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate + T result = (((double)uiTemp) / streflop::pow((streflop::Simple)10,(streflop::Simple)precision) * iSigned); +#else + unsigned int uiTemp = (value * pow(10, precision)) * iSigned; //Note I'm using unsigned int so that I can increase the precision of the truncate + T result = (((double)uiTemp) / pow(10,precision) * iSigned); +#endif + return result; +} + + }}//end namespace #endif diff --git a/source/shared_lib/include/graphics/particle.h b/source/shared_lib/include/graphics/particle.h index 95336539..c2974889 100644 --- a/source/shared_lib/include/graphics/particle.h +++ b/source/shared_lib/include/graphics/particle.h @@ -277,6 +277,8 @@ private: Vec3f fixedAddition; Vec3f oldPosition; bool energyUp; + float startTime; + float endTime; public: enum Shape{ @@ -315,6 +317,11 @@ public: virtual void fade(); virtual void render(ParticleRenderer *pr, ModelRenderer *mr); + virtual void setStartTime(float startTime) { this->startTime = startTime; } + virtual float getStartTime() const { return this->startTime; } + virtual void setEndTime(float endTime) { this->endTime = endTime; } + virtual float getEndTime() const { return this->endTime; } + //set params void setRadius(float radius) {this->radius= radius;} void setMinRadius(float minRadius) {this->minRadius= minRadius;} diff --git a/source/shared_lib/sources/graphics/particle.cpp b/source/shared_lib/sources/graphics/particle.cpp index a12f27a5..8620fb62 100644 --- a/source/shared_lib/sources/graphics/particle.cpp +++ b/source/shared_lib/sources/graphics/particle.cpp @@ -553,6 +553,9 @@ UnitParticleSystem::UnitParticleSystem(int particleCount): delay = 0; // none lifetime = -1; // forever + + startTime = 0; + endTime = 1; } UnitParticleSystem::~UnitParticleSystem(){