NLS Engine  v0.1
The Next Logical Step in game engine design.
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Defines
EntityList.h
Go to the documentation of this file.
00001 #pragma once
00002 
00013 // Standard Includes
00014 #include <map>
00015 #include <string>
00016 
00017 // Library Includes
00018 #include <boost/foreach.hpp>
00019 #include <threading.h>
00020 
00021 // Local Includes
00022 #include "EventLogger.h"
00023 #include "Entity.h"
00024 
00025 // Forward Declarations
00026 
00027 // Typedefs
00028 struct MutableStringSPTRCompare {
00029   bool operator() (const MutableStringSPTR& lhs, const MutableStringSPTR& rhs) const {
00030     return *lhs < *rhs;
00031   }
00032 };
00033 
00034 typedef std::map<MutableStringSPTR, EntitySPTR, MutableStringSPTRCompare> NamedEntityMap;
00035 typedef NamedEntityMap::value_type NamedEntity;
00036 
00037 
00038 class EntityList {
00039 public:
00040   EntityList(void) : debug_output(true) { }
00041   ~EntityList(void) {
00042   }
00043   
00044   bool AddEntity(EntitySPTR const entity) {
00045     return AddEntity("", entity);
00046   }
00047   
00048   bool AddEntity(const std::string name, EntitySPTR const entity) {
00049     if (entity.get() != nullptr) {
00050       Threading::UpgradeLock up_lock(this->mutex);
00051       
00052       // Don't change the name if the entity already has a name.
00053       {
00054         MutableStringSPTR ent_name(entity->GetNameSPTR());
00055         if (ent_name.get() == nullptr || ent_name->length() <= 0) {
00056           // Make sure there's a name to use.
00057           if (name.length() > 0) {
00058             entity->SetName(name);
00059           }
00060           else {
00061             LOG(LOG_PRIORITY::CONFIG, "ERROR: Entity must have a name to be added!");
00062             return false;
00063           }
00064         }
00065         else if (name.length() > 0) {
00066           LOG(LOG_PRIORITY::INFO, "WARNING: Attempt to rename Entity '" + *ent_name.get() + "' to '" + name + "' during addition to EntList was ignored!");
00067         }
00068         // else: a name of "" and a fully named entity is a valid operation.
00069       }
00070       
00071       MutableStringSPTR name_sptr(entity->GetNameSPTR());
00072       
00073       if (this->entities.find(name_sptr) == this->entities.end()) {
00074         Threading::UpgradeToUniqueLock unique_lock(up_lock);
00075         
00076         EntitySPTR ent(entity);
00077         this->entities.insert(NamedEntity(name_sptr, ent));
00078         
00079         LOG2(LOG_PRIORITY::FLOW, "Adding entity: '" + *name_sptr.get() + "'");
00080         return true;
00081       }
00082       else {
00083         LOG(LOG_PRIORITY::CONFIG, "ERROR: Entity '" + *name_sptr.get() + "', already exists.");
00084         return false;
00085       }
00086     }
00087     else {
00088       LOG(LOG_PRIORITY::CONFIG, "ERROR: Adding a null entity is an invalid operation.  Attempted to add with the name '" + name + "'");
00089       
00090       return false;
00091     }
00092   }
00093   
00094   EntitySPTR FindEntity(const std::string name) const {
00095     Threading::ReadLock r_lock(this->mutex);
00096     
00097     MutableStringSPTR name_sptr(new std::string(name));
00098     
00099     NamedEntityMap::const_iterator entitymap_it = this->entities.find(name_sptr);
00100     if (entitymap_it != this->entities.end()) {
00101       EntitySPTR found_entity((*entitymap_it).second);
00102       
00103       return found_entity;
00104     }
00105     else {
00106       LOG2(LOG_PRIORITY::CONFIG, "Entity '" + name +  "' not found.  Did you forget to name it?  Or have you already removed it?");
00107       return nullptr;
00108     }
00109   }
00110   
00111   std::string FindName(EntitySPTR const entity) const {
00112     if (entity.get() != nullptr) {
00113       return entity->GetName();
00114     }
00115     else {
00116       return "";
00117     }
00118   }
00119   
00120   bool RemoveEntity(const std::string name) {
00121     Threading::WriteLock w_lock(this->mutex);
00122     
00123     MutableStringSPTR name_sptr(new std::string(name));
00124     
00125     NamedEntityMap::const_iterator entitymap_it = this->entities.find(name_sptr);
00126     if (entitymap_it != this->entities.end()) {
00127       LOG2(LOG_PRIORITY::FLOW, "Removing entity '" + name + "' and deleting it.");
00128       
00129       EntitySPTR ent((*entitymap_it).second);
00130       
00131       this->entities.erase(entitymap_it);
00132       
00133       ent->ClearComponents();
00134       
00135       // Let all the entities know that the selected entity has been removed.
00136       // *TODO: build a structure that makes this not have to iterate through every entity.
00137       BOOST_FOREACH(NamedEntity& named_entity, this->entities) {
00138         EntitySPTR entity(named_entity.second);
00139         bool ret = entity->NotifyEntityRemoval(ent);
00140       }
00141       
00142       return true;
00143     }
00144     
00145     LOG2(LOG_PRIORITY::CONFIG, "Entity '" + name +  "' not found. Unable to remove and delete.  Did you add it to the EntityList?");
00146     return false;
00147   }
00148 
00149   bool debug_output;
00150 private:
00151   mutable Threading::ReadWriteMutex mutex;
00152   NamedEntityMap entities;
00153 };