#ifndef World_h__ #define World_h__ #include #include #include #include #include #include #include #include "logging.h" #include "Factory.h" #include "Entity.h" #include "Component.h" #include "System.h" class World { public: World(); ~World(); virtual void Initialize(); virtual void RegisterSystems() = 0; virtual void AddSystems() = 0; virtual void RegisterComponents() = 0; void AddSystem(std::string systemType); template std::shared_ptr GetSystem(std::string systemType); EntityID CreateEntity(EntityID parent = 0); void RemoveEntity(EntityID entity); bool ValidEntity(EntityID entity); EntityID GetEntityParent(EntityID entity); template T GetProperty(EntityID entity, std::string property) { if(m_EntityProperties.find(entity) == m_EntityProperties.end()) return T(); if(m_EntityProperties[entity].find(property) == m_EntityProperties[entity].end()) return T(); return boost::any_cast(m_EntityProperties[entity][property]); } void SetProperty(EntityID entity, std::string property, boost::any value) { m_EntityProperties[entity][property] = value; } template std::shared_ptr AddComponent(EntityID entity, std::string componentType); std::shared_ptr AddComponent(EntityID entity, std::string componentType); template T* GetComponent(EntityID entity, std::string componentType); /*std::vector GetEntityChildren(EntityID entity);*/ virtual void Update(double dt); // Recursively update through the scene graph void RecursiveUpdate(std::shared_ptr system, double dt, EntityID parentEntity); std::unordered_map* GetEntities() { return &m_EntityParents; } protected: SystemFactory m_SystemFactory; ComponentFactory m_ComponentFactory; std::unordered_map> m_Systems; EntityID m_LastEntityID; std::stack m_RecycledEntityIDs; // A bottom to top tree. A map of child entities to parent entities. std::unordered_map m_EntityParents ; std::unordered_map> m_EntityProperties; std::unordered_map>> m_ComponentsOfType; std::unordered_map>> m_EntityComponents; std::list m_EntitiesToRemove; void ProcessEntityRemovals(); EntityID GenerateEntityID(); void RecycleEntityID(EntityID id); }; template std::shared_ptr World::GetSystem(std::string systemType) { return std::static_pointer_cast(m_Systems[systemType]); } template std::shared_ptr World::AddComponent(EntityID entity, std::string componentType) { std::shared_ptr component = std::shared_ptr(static_cast(m_ComponentFactory.Create(componentType))); if (component == nullptr) { LOG_ERROR("Failed to attach invalid component \"%s\" to entity #%i", componentType.c_str(), entity); return nullptr; } component->Entity = entity; m_ComponentsOfType[componentType].push_back(component); m_EntityComponents[entity][componentType] = component; for (auto pair : m_Systems) { auto system = pair.second; system->OnComponentCreated(componentType, component); } return component; } template T* World::GetComponent(EntityID entity, std::string componentType) { return (T*)m_EntityComponents[entity][componentType].get(); } #endif // World_h__