// Copyright (C) 2015 Jérôme Leclercq // This file is part of the "Nazara Development Kit" // For conditions of distribution and use, see copyright notice in Prerequesites.hpp #include #include #include namespace Ndk { /*! * \brief Constructs a BaseSystem object with an index * * \param systemId Index of the system */ inline BaseSystem::BaseSystem(SystemIndex systemId) : m_systemIndex(systemId), m_world(nullptr), m_updateEnabled(true), m_updateOrder(0) { SetUpdateRate(30); } /*! * \brief Constructs a BaseSystem object by copy semantic * * \param system System to copy */ inline BaseSystem::BaseSystem(const BaseSystem& system) : m_excludedComponents(system.m_excludedComponents), m_requiredComponents(system.m_requiredComponents), m_systemIndex(system.m_systemIndex), m_updateEnabled(system.m_updateEnabled), m_updateCounter(0.f), m_updateRate(system.m_updateRate), m_updateOrder(system.m_updateOrder) { } /*! * \brief Enables the system * * \param enable Should the system be enabled */ inline void BaseSystem::Enable(bool enable) { m_updateEnabled = enable; } /*! * \brief Gets every entities that system handle * \return A constant reference to the list of entities */ inline const std::vector& BaseSystem::GetEntities() const { return m_entities; } /*! * \brief Gets the index of the system * \return Index of the system */ inline SystemIndex BaseSystem::GetIndex() const { return m_systemIndex; } /*! * \brief Gets the update order of the system * \return Update order * * \see SetUpdateOrder */ inline int BaseSystem::GetUpdateOrder() const { return m_updateOrder; } /*! * \brief Gets the rate of update of the system * \return Update rate */ inline float BaseSystem::GetUpdateRate() const { return (m_updateRate > 0.f) ? 1.f / m_updateRate : 0.f; } /*! * \brief Gets the world on which the system operate * \return World in which the system is */ inline World& BaseSystem::GetWorld() const { return *m_world; } /*! * \brief Checks whether or not the system is enabled * \return true If it is the case */ inline bool BaseSystem::IsEnabled() const { return m_updateEnabled; } /*! * \brief Checks whether or not the system has the entity * \return true If it is the case * * \param entity Pointer to the entity */ inline bool BaseSystem::HasEntity(const Entity* entity) const { if (!entity) return false; return m_entityBits.UnboundedTest(entity->GetId()); } /*! * \brief Sets the rate of update for the system * * \param updatePerSecond Update rate, 0 means as much as possible */ inline void BaseSystem::SetUpdateRate(float updatePerSecond) { m_updateCounter = 0.f; m_updateRate = (updatePerSecond > 0.f) ? 1.f / updatePerSecond : 0.f; // 0.f means no limit } /*! * \brief Updates the system * * \param elapsedTime Delta time used for the update */ inline void BaseSystem::Update(float elapsedTime) { if (!IsEnabled()) return; if (m_updateRate > 0.f) { m_updateCounter += elapsedTime; while (m_updateCounter >= m_updateRate) { OnUpdate(m_updateRate); m_updateCounter -= m_updateRate; } } else OnUpdate(elapsedTime); } /*! * \brief Excludes some component from the system */ template void BaseSystem::Excludes() { static_assert(std::is_base_of::value , "ComponentType is not a component"); ExcludesComponent(GetComponentIndex()); } /*! * \brief Excludes some components from the system */ template void BaseSystem::Excludes() { Excludes(); Excludes(); } /*! * \brief Excludes some component from the system by index * * \param index Index of the component */ inline void BaseSystem::ExcludesComponent(ComponentIndex index) { m_excludedComponents.UnboundedSet(index); } /*! * \brief Gets the next index for the system * \return Next unique index for the system */ inline SystemIndex BaseSystem::GetNextIndex() { return s_nextIndex++; } /*! * \brief Requires some component from the system */ template void BaseSystem::Requires() { static_assert(std::is_base_of::value, "ComponentType is not a component"); RequiresComponent(GetComponentIndex()); } /*! * \brief Requires some components from the system */ template void BaseSystem::Requires() { Requires(); Requires(); } /*! * \brief Requires some component for the system by index * * \param index Index of the component */ inline void BaseSystem::RequiresComponent(ComponentIndex index) { m_requiredComponents.UnboundedSet(index); } /*! * \brief Requires any component from the system */ template void BaseSystem::RequiresAny() { static_assert(std::is_base_of::value, "ComponentType is not a component"); RequiresAnyComponent(GetComponentIndex()); } /*! * \brief Requires any components from the system */ template void BaseSystem::RequiresAny() { RequiresAny(); RequiresAny(); } /*! * \brief Requires any component for the system by index * * \param index Index of the component */ inline void BaseSystem::RequiresAnyComponent(ComponentIndex index) { m_requiredAnyComponents.UnboundedSet(index); } /*! * \brief Adds an entity to a system * * \param entity Pointer to the entity * * \remark Produces a NazaraAssert if entity is invalid */ inline void BaseSystem::AddEntity(Entity* entity) { NazaraAssert(entity, "Invalid entity"); m_entities.emplace_back(entity); m_entityBits.UnboundedSet(entity->GetId(), true); entity->RegisterSystem(m_systemIndex); OnEntityAdded(entity); } /*! * \brief Removes an entity to a system * * \param entity Pointer to the entity * * \remark Produces a NazaraAssert if entity is invalid */ inline void BaseSystem::RemoveEntity(Entity* entity) { NazaraAssert(entity, "Invalid entity"); auto it = std::find(m_entities.begin(), m_entities.end(), *entity); NazaraAssert(it != m_entities.end(), "Entity is not part of this system"); // To avoid moving a lot of handles, we swap and pop std::swap(*it, m_entities.back()); m_entities.pop_back(); // We get it out of the vector m_entityBits.Reset(entity->GetId()); entity->UnregisterSystem(m_systemIndex); OnEntityRemoved(entity); // And we alert our callback } /*! * \brief Validates an entity to a system * * \param entity Pointer to the entity * \param justAdded Is the entity newly added * * \remark Produces a NazaraAssert if entity is invalid or if system does not hold this entity */ inline void BaseSystem::ValidateEntity(Entity* entity, bool justAdded) { NazaraAssert(entity, "Invalid entity"); NazaraAssert(HasEntity(entity), "Entity should be part of system"); OnEntityValidation(entity, justAdded); } /*! * \brief Sets the world on which the system operates */ inline void BaseSystem::SetWorld(World* world) noexcept { m_world = world; } /*! * \brief Initializes the BaseSystem * \return true */ inline bool BaseSystem::Initialize() { s_nextIndex = 0; return true; } /*! * \brief Uninitializes the BaseSystem */ inline void BaseSystem::Uninitialize() { // Nothing to do } }