#ifndef World_h__ #define World_h__ #include #include #include #include #include #include #include #include #include "Factory.h" #include "Entity.h" #include "Component.h" #include "Components/Template.h" #include "System.h" #include "EventBroker.h" #include "ResourceManager.h" class World { public: World(std::shared_ptr<::EventBroker> eventBroker) : m_EventBroker(eventBroker) , m_LastEntityID(0) { } ~World() { } virtual void Initialize(); virtual void RegisterSystems() = 0; virtual void AddSystems() = 0; virtual void RegisterComponents() = 0; template void AddSystem() { m_Systems[typeid(T).name()] = std::shared_ptr(m_SystemFactory.Create()); } template std::shared_ptr GetSystem(); EntityID CreateEntity(EntityID parent = 0); EntityID CloneEntity(EntityID entity, EntityID parent = 0); void RemoveEntity(EntityID entity); bool ValidEntity(EntityID entity); EntityID GetEntityParent(EntityID entity); EntityID GetEntityBaseParent(EntityID entity); std::list GetEntityChildren(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; } void SetProperty(EntityID entity, std::string property, char* value) { m_EntityProperties[entity][property] = std::string(value); } template std::shared_ptr AddComponent(EntityID entity); template void RemoveComponent(EntityID entity); template T* GetComponent(EntityID entity); // Triggers commit events in systems void CommitEntity(EntityID entity); template std::list>* GetComponentsOfType(); /*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; } ResourceManager* GetResourceManager() { return &m_ResourceManager; } std::shared_ptr<::EventBroker> EventBroker() { return m_EventBroker; } protected: std::shared_ptr<::EventBroker> m_EventBroker; SystemFactory m_SystemFactory; ComponentFactory m_ComponentFactory; ResourceManager m_ResourceManager; std::unordered_map> m_Systems; EntityID m_LastEntityID; std::stack m_RecycledEntityIDs; std::unordered_map m_EntityParents; // child -> parent std::unordered_map> m_EntityChildren; // parent -> child std::unordered_map> m_EntityProperties; std::unordered_map>> m_ComponentsOfType; std::unordered_map>> m_EntityComponents; // Internal: Add a component to an entity void AddComponent(EntityID entity, std::string componentType, std::shared_ptr component); std::set m_EntitiesToRemove; void ProcessEntityRemovals(); EntityID GenerateEntityID(); void RecycleEntityID(EntityID id); }; template std::list>* World::GetComponentsOfType() { const char* componentType = typeid(T).name(); auto it = m_ComponentsOfType.find(componentType); if (it == m_ComponentsOfType.end()) return nullptr; return &it->second; } template std::shared_ptr World::GetSystem() { const char* systemType = typeid(T).name(); if (m_Systems.find(systemType) == m_Systems.end()) { LOG_WARNING("Tried to get pointer to unregistered system \"%s\"!", systemType); return nullptr; } return std::static_pointer_cast(m_Systems.at(systemType)); } template std::shared_ptr World::AddComponent(EntityID entity) { const char* componentType = typeid(T).name(); std::shared_ptr component = std::shared_ptr(static_cast(m_ComponentFactory.Create())); if (component == nullptr) { LOG_ERROR("Failed to attach invalid component \"%s\" to entity #%i", componentType, entity); return nullptr; } AddComponent(entity, componentType, component); return component; } template void World::RemoveComponent(EntityID entity) { const char* componentType = typeid(T).name(); auto it = m_EntityComponents[entity].find(componentType); if (it == m_EntityComponents[entity].end()) return; auto component = it->second; component->Entity = 0; m_ComponentsOfType[componentType].remove(component); m_EntityComponents[entity].erase(it); for (auto pair : m_Systems) { auto system = pair.second; system->OnComponentRemoved(entity, componentType, component.get()); } } template T* World::GetComponent(EntityID entity) { auto components = m_EntityComponents[entity]; auto it = components.find(typeid(T).name()); if (it != components.end()) { return static_cast(it->second.get()); } else { return nullptr; } } #endif // World_h__