// ============================================================== // This file is part of Glest (www.glest.org) // // Copyright (C) 2001-2008 MartiƱo Figueroa // // 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 "object.h" #include "faction_type.h" #include "config.h" #include "tech_tree.h" #include "resource.h" #include "upgrade.h" #include "object_type.h" #include "resource.h" #include "util.h" #include "randomgen.h" #include "renderer.h" #include "leak_dumper.h" #include "game.h" using namespace Shared::Util; namespace Glest{ namespace Game{ ObjectStateInterface *Object::stateCallback=NULL; // ===================================================== // class Object // ===================================================== Object::Object(ObjectType *objectType, const Vec3f &pos, const Vec2i &mapPos) : BaseColorPickEntity() { RandomGen random; random.init(static_cast(pos.x * pos.z)); this->lastRenderFrame = 0; this->objectType= objectType; resource= NULL; highlight= 0.f; animated= false; this->mapPos = mapPos; this->pos= pos + Vec3f(random.randRange(-0.6f, 0.6f), 0.0f, random.randRange(-0.6f, 0.6f)); rotation= random.randRange(0.f, 360.f); if(objectType!=NULL){ variation = random.randRange(0, objectType->getModelCount()-1); TilesetModelType *tmt=objectType->getTilesetModelType(variation); if(tmt->getRotationAllowed() != true) { rotation=0; } if(tmt->getRandomPositionEnabled() != true) { this->pos = pos; } animated=tmt->getAnimSpeed()>0; } else { variation=0; } visible=false; animProgress=0.0f; } Object::~Object() { Renderer &renderer = Renderer::getInstance(); // fade(and by this remove) all unit particle systems while(unitParticleSystems.empty() == false) { bool particleValid = renderer.validateParticleSystemStillExists(unitParticleSystems.back(),rsGame); if(particleValid == true) { unitParticleSystems.back()->fade(); } unitParticleSystems.pop_back(); } Renderer::getInstance().removeParticleSystemsForParticleOwner(this,rsGame); renderer.removeObjectFromQuadCache(this); if(stateCallback) { stateCallback->removingObjectEvent(this); } delete resource; resource = NULL; } void Object::end() { // set Objects to fading and remove them from list. // its needed because otherwise they will be accessed from the destructor while(unitParticleSystems.empty() == false) { bool particleValid = Renderer::getInstance().validateParticleSystemStillExists(unitParticleSystems.back(),rsGame); if(particleValid == true) { unitParticleSystems.back()->fade(); } unitParticleSystems.pop_back(); } } void Object::initParticles() { if(this->objectType == NULL) { return; } if(this->objectType->getTilesetModelType(variation)->hasParticles()) { ModelParticleSystemTypes *particleTypes= this->objectType->getTilesetModelType(variation)->getParticleTypes(); initParticlesFromTypes(particleTypes); } } void Object::initParticlesFromTypes(const ModelParticleSystemTypes *particleTypes) { bool showTilesetParticles = Config::getInstance().getBool("TilesetParticles", "true"); if(showTilesetParticles == true && GlobalStaticFlags::getIsNonGraphicalModeEnabled() == false && particleTypes->empty() == false && unitParticleSystems.empty() == true) { for(ObjectParticleSystemTypes::const_iterator it= particleTypes->begin(); it != particleTypes->end(); ++it){ UnitParticleSystem *ups= new UnitParticleSystem(200); ups->setParticleOwner(this); ups->setParticleType((*it)); (*it)->setValues(ups); ups->setPos(this->pos); ups->setRotation(this->rotation); ups->setFactionColor(Vec3f(0, 0, 0)); ups->setVisible(false); this->unitParticleSystems.push_back(ups); Renderer::getInstance().manageParticleSystem(ups, rsGame); } } } void Object::end(ParticleSystem *particleSystem) { vector::iterator iterFind = find(unitParticleSystems.begin(),unitParticleSystems.end(),particleSystem); if(iterFind != unitParticleSystems.end()) { unitParticleSystems.erase(iterFind); } } void Object::setHeight(float height) { pos.y = height; for(UnitParticleSystems::iterator it= unitParticleSystems.begin(); it != unitParticleSystems.end(); ++it) { bool particleValid = Renderer::getInstance().validateParticleSystemStillExists((*it),rsGame); if(particleValid == true) { (*it)->setPos(this->pos); } } } void Object::updateHighlight() { //highlight if(highlight > 0.f) { //const Game *game = Renderer::getInstance().getGame(); //highlight -= 1.f / (Game::highlightTime * game->getWorld()->getUpdateFps(-1)); highlight -= 1.f / (Game::highlightTime * GameConstants::updateFps); } } void Object::update() { //if(objectType != NULL && objectType->getTilesetModelType(variation) != NULL && // objectType->getTilesetModelType(variation)->getAnimSpeed() != 0.0) { if(animated == true) { // printf("#1 Object updating [%s] Speed [%d] animProgress [%f]\n",this->objectType->getTilesetModelType(variation)->getModel()->getFileName().c_str(),objectType->getTilesetModelType(variation)->getAnimSpeed(),animProgress); if(objectType != NULL && objectType->getTilesetModelType(variation) != NULL) { float heightFactor = 1.f; const float speedDivider= 100.f; float speedDenominator = (speedDivider * GameConstants::updateFps); // smooth TwoFrameanimations float f=1.0f; if(objectType->getTilesetModelType(variation)->getSmoothTwoFrameAnim()==true){ f=abs(std::sin(animProgress*2*3.16))+0.4f; } float newAnimProgress = animProgress + f*(((float)objectType->getTilesetModelType(variation)->getAnimSpeed() * heightFactor) / speedDenominator); animProgress = newAnimProgress; if(animProgress > 1.f) { animProgress = 0.f; } } } } void Object::resetHighlight(){ highlight= 1.f; } Model *Object::getModelPtr() const { Model* result = NULL; if(objectType==NULL) { if(resource != NULL && resource->getType() != NULL){ result = resource->getType()->getModel(); } } else { result=objectType->getTilesetModelType(variation)->getModel(); } return result; } const Model *Object::getModel() const { Model* result = NULL; if(objectType == NULL){ if(resource != NULL && resource->getType() != NULL){ result=resource->getType()->getModel(); } } else { result=objectType->getTilesetModelType(variation)->getModel(); } return result; } bool Object::getWalkable() const{ return objectType==NULL? false: objectType->getWalkable(); } void Object::setResource(const ResourceType *resourceType, const Vec2i &pos){ delete resource; resource= new Resource(); resource->init(resourceType, pos); initParticlesFromTypes(resourceType->getObjectParticleSystemTypes()); } void Object::setVisible( bool visible) { this->visible=visible; for(UnitParticleSystems::iterator it= unitParticleSystems.begin(); it != unitParticleSystems.end(); ++it) { bool particleValid = Renderer::getInstance().validateParticleSystemStillExists((*it),rsGame); if(particleValid == true) { (*it)->setVisible(visible); } } } string Object::getUniquePickName() const { string result = ""; if(resource != NULL) { result += resource->getDescription(false) + " : "; } result += mapPos.getString(); return result; } void Object::saveGame(XmlNode *rootNode) { std::map mapTagReplacements; XmlNode *objectNode = rootNode->addChild("Object"); // ObjectType *objectType; if(objectType != NULL) { objectNode->addAttribute("objectType",intToStr(objectType->getClass()), mapTagReplacements); } // vector unitParticleSystems; for(unsigned int i = 0; i < unitParticleSystems.size(); ++i) { UnitParticleSystem *ptr= unitParticleSystems[i]; if(ptr != NULL) { ptr->saveGame(objectNode); } } // Resource *resource; if(resource != NULL) { resource->saveGame(objectNode); } // Vec3f pos; objectNode->addAttribute("pos",pos.getString(), mapTagReplacements); // float rotation; objectNode->addAttribute("rotation",floatToStr(rotation,6), mapTagReplacements); // int variation; objectNode->addAttribute("variation",intToStr(variation), mapTagReplacements); // int lastRenderFrame; objectNode->addAttribute("lastRenderFrame",intToStr(lastRenderFrame), mapTagReplacements); // Vec2i mapPos; objectNode->addAttribute("mapPos",mapPos.getString(), mapTagReplacements); // bool visible; objectNode->addAttribute("visible",intToStr(visible), mapTagReplacements); } void Object::loadGame(const XmlNode *rootNode,const TechTree *techTree) { const XmlNode *objectNode = rootNode->getChild("Object"); //description = objectNode->getAttribute("description")->getValue(); // ObjectType *objectType; // if(objectType != NULL) { // objectNode->addAttribute("objectType",intToStr(objectType->getClass()), mapTagReplacements); // } // // vector unitParticleSystems; // for(unsigned int i = 0; i < unitParticleSystems.size(); ++i) { // UnitParticleSystem *ptr= unitParticleSystems[i]; // if(ptr != NULL) { // ptr->saveGame(objectNode); // } // } // Resource *resource; if(resource != NULL) { resource->loadGame(objectNode,0,techTree); } // Vec3f pos; pos = Vec3f::strToVec3(objectNode->getAttribute("pos")->getValue()); // float rotation; rotation = objectNode->getAttribute("rotation")->getFloatValue(); // int variation; variation = objectNode->getAttribute("variation")->getIntValue(); // int lastRenderFrame; lastRenderFrame = objectNode->getAttribute("lastRenderFrame")->getIntValue(); // Vec2i mapPos; mapPos = Vec2i::strToVec2(objectNode->getAttribute("mapPos")->getValue()); // bool visible; visible = objectNode->getAttribute("visible")->getIntValue() != 0; } }}//end namespace