ARGoS
3
A parallel, multi-engine simulator for swarm robotics
|
00001 00013 #ifndef ENTITY_H 00014 #define ENTITY_H 00015 00016 namespace argos { 00017 class CEntity; 00018 class CComposableEntity; 00019 class CSpace; 00020 } 00021 00022 #include <argos3/core/utility/datatypes/datatypes.h> 00023 #include <argos3/core/utility/configuration/argos_configuration.h> 00024 #include <argos3/core/utility/configuration/base_configurable_resource.h> 00025 #include <argos3/core/utility/plugins/factory.h> 00026 #include <argos3/core/utility/plugins/vtable.h> 00027 00028 #include <vector> 00029 #include <map> 00030 #include <string> 00031 00032 #if defined(__apple_build_version__ ) 00033 // We are on Apple, check compiler version 00034 # if __clang_major__ >= 5 00035 // XCode 5.0.0 or later 00036 # include <unordered_map> 00037 using std::unordered_map; 00038 # else 00039 // XCode 4.6.3 or earlier 00040 # include <tr1/unordered_map> 00041 using std::tr1::unordered_map; 00042 # endif 00043 #else 00044 // We are on Linux, use c++03 standard 00045 # include <tr1/unordered_map> 00046 using std::tr1::unordered_map; 00047 #endif 00048 00049 namespace argos { 00050 00089 class CEntity : public CBaseConfigurableResource, 00090 public EnableVTableFor<CEntity> { 00091 00092 public: 00093 00094 ENABLE_VTABLE(); 00095 00097 typedef std::vector<CEntity*> TVector; 00098 00100 typedef unordered_map<std::string, CEntity*> TMap; 00101 00103 typedef std::multimap<std::string, CEntity*> TMultiMap; 00104 00105 public: 00106 00112 CEntity(CComposableEntity* pc_parent); 00113 00122 CEntity(CComposableEntity* pc_parent, 00123 const std::string& str_id); 00124 00128 virtual ~CEntity() {} 00129 00139 virtual void Init(TConfigurationNode& t_tree); 00140 00145 virtual void Reset() {} 00146 00151 virtual void Destroy() {} 00152 00157 inline const std::string& GetId() const { 00158 return m_strId; 00159 } 00160 00165 std::string GetContext() const; 00166 00171 inline bool HasParent() const { 00172 return (m_pcParent != NULL); 00173 } 00174 00179 CEntity& GetRootEntity(); 00180 00185 const CEntity& GetRootEntity() const; 00186 00192 CComposableEntity& GetParent(); 00193 00199 const CComposableEntity& GetParent() const; 00200 00205 inline void SetParent(CComposableEntity& c_parent) { 00206 m_pcParent = &c_parent; 00207 } 00208 00213 virtual std::string GetTypeDescription() const { 00214 return "entity"; 00215 } 00216 00221 virtual void Update() {} 00222 00229 bool IsEnabled() const { 00230 return m_bEnabled; 00231 } 00232 00239 inline void Enable() { 00240 SetEnabled(true); 00241 } 00242 00249 inline void Disable() { 00250 SetEnabled(false); 00251 } 00252 00259 virtual void SetEnabled(bool b_enabled); 00260 00267 bool CanBeEnabledIfDisabled() const { 00268 return m_bCanBeEnabledIfDisabled; 00269 } 00270 00277 void SetCanBeEnabledIfDisabled(bool b_can_it) { 00278 m_bCanBeEnabledIfDisabled = b_can_it; 00279 } 00280 00281 private: 00282 00284 CComposableEntity* m_pcParent; 00285 00287 std::string m_strId; 00288 00290 bool m_bEnabled; 00291 00298 bool m_bCanBeEnabledIfDisabled; 00299 00300 }; 00301 00305 template <typename LABEL, typename PLUGIN, typename RETURN_TYPE> 00306 class CEntityOperation { 00307 public: 00308 template <typename DERIVED, typename OPERATION_IMPL> 00309 RETURN_TYPE Hook(PLUGIN& t_plugin, CEntity& c_entity) { 00310 return Dispatch<DERIVED, OPERATION_IMPL>(t_plugin, c_entity); 00311 } 00312 protected: 00313 template <typename DERIVED, typename OPERATION_IMPL> 00314 RETURN_TYPE Dispatch(PLUGIN& t_plugin, CEntity& c_entity) { 00315 /* First dispatch: cast this operation into the specific operation */ 00316 OPERATION_IMPL& tOperation = static_cast<OPERATION_IMPL&>(*this); 00317 /* Second dispatch: cast t_base to DERIVED */ 00318 DERIVED& tDerived = static_cast<DERIVED&>(c_entity); 00319 /* Perform visit */ 00320 return tOperation.ApplyTo(t_plugin, tDerived); 00321 } 00322 }; 00323 00327 template <typename LABEL, typename PLUGIN, typename RETURN_TYPE> 00328 class CEntityOperationInstanceHolder { 00329 public: 00330 ~CEntityOperationInstanceHolder() { 00331 while(!m_vecOperationInstances.empty()) { 00332 if(m_vecOperationInstances.back() != NULL) { 00333 delete m_vecOperationInstances.back(); 00334 } 00335 m_vecOperationInstances.pop_back(); 00336 } 00337 } 00338 template <typename DERIVED> 00339 void Add(CEntityOperation<LABEL, PLUGIN, RETURN_TYPE>* pc_operation) { 00340 /* Find the slot */ 00341 size_t unIndex = GetTag<DERIVED, CEntity>(); 00342 /* Does the holder have a slot for this index? */ 00343 if(unIndex >= m_vecOperationInstances.size()) { 00344 /* No, new slots must be created 00345 * Fill the slots with NULL 00346 */ 00347 /* Create new slots up to index+1 and fill them with tDefaultFunction */ 00348 m_vecOperationInstances.resize(unIndex+1, NULL); 00349 } 00350 m_vecOperationInstances[unIndex] = pc_operation; 00351 } 00352 CEntityOperation<LABEL, PLUGIN, RETURN_TYPE>* operator[](size_t un_index) const { 00353 if(un_index >= m_vecOperationInstances.size()) { 00354 return NULL; 00355 } 00356 return m_vecOperationInstances[un_index]; 00357 } 00358 private: 00359 std::vector<CEntityOperation<LABEL, PLUGIN, RETURN_TYPE>*> m_vecOperationInstances; 00360 }; 00369 template <typename LABEL, typename PLUGIN, typename RETURN_VALUE> 00370 CEntityOperationInstanceHolder<LABEL, PLUGIN, RETURN_VALUE>& GetEntityOperationInstanceHolder() { 00371 static CEntityOperationInstanceHolder<LABEL, PLUGIN, RETURN_VALUE> cHolder; 00372 return cHolder; 00373 } 00382 template<typename LABEL, typename PLUGIN, typename RETURN_VALUE> 00383 RETURN_VALUE CallEntityOperation(PLUGIN& t_plugin, CEntity& c_entity) { 00384 typedef RETURN_VALUE (CEntityOperation<LABEL, PLUGIN, RETURN_VALUE>::*TFunction)(PLUGIN& t_plugin, CEntity&); 00385 TFunction tFunction = GetVTable<LABEL, CEntity, TFunction>()[c_entity.GetTag()]; 00386 if(tFunction != NULL) { 00387 CEntityOperation<LABEL, PLUGIN, RETURN_VALUE>* pcOperation = GetEntityOperationInstanceHolder<LABEL, PLUGIN, RETURN_VALUE>()[c_entity.GetTag()]; 00388 if(pcOperation != NULL) { 00389 return (pcOperation->*tFunction)(t_plugin, c_entity); 00390 } 00391 } 00392 return RETURN_VALUE(); 00393 } 00394 00395 } 00396 00397 #define REGISTER_ENTITY(CLASSNAME, \ 00398 LABEL, \ 00399 AUTHOR, \ 00400 VERSION, \ 00401 BRIEF_DESCRIPTION, \ 00402 LONG_DESCRIPTION, \ 00403 STATUS) \ 00404 REGISTER_SYMBOL(CEntity, \ 00405 CLASSNAME, \ 00406 LABEL, \ 00407 AUTHOR, \ 00408 VERSION, \ 00409 BRIEF_DESCRIPTION, \ 00410 LONG_DESCRIPTION, \ 00411 STATUS) 00412 00416 #define REGISTER_ENTITY_OPERATION(LABEL, PLUGIN, OPERATION, RETURN_VALUE, DERIVED) \ 00417 class C ## LABEL ## PLUGIN ## OPERATION ## RETURN_VALUE ## DERIVED { \ 00418 typedef RETURN_VALUE (CEntityOperation<LABEL, PLUGIN, RETURN_VALUE>::*TFunction)(PLUGIN&, CEntity&); \ 00419 public: \ 00420 C ## LABEL ## PLUGIN ## OPERATION ## RETURN_VALUE ## DERIVED() { \ 00421 GetVTable<LABEL, CEntity, TFunction>().Add<DERIVED>(&OPERATION::Hook<DERIVED, OPERATION>); \ 00422 GetEntityOperationInstanceHolder<LABEL, PLUGIN, RETURN_VALUE>().Add<DERIVED>(new OPERATION()); \ 00423 } \ 00424 } c ## LABEL ## PLUGIN ## OPERATION ## RETURN_VALUE ## DERIVED; 00425 00426 #endif