SDK: Allow to set an update order for systems (Closes #106)

This commit is contained in:
Jérôme Leclercq 2016-11-08 02:51:25 +01:00
parent 4570f9a6e1
commit aa304ef2e9
6 changed files with 97 additions and 32 deletions

View File

@ -35,6 +35,7 @@ namespace Ndk
inline const std::vector<EntityHandle>& GetEntities() const; inline const std::vector<EntityHandle>& GetEntities() const;
inline SystemIndex GetIndex() const; inline SystemIndex GetIndex() const;
inline int GetUpdateOrder() const;
inline float GetUpdateRate() const; inline float GetUpdateRate() const;
inline World& GetWorld() const; inline World& GetWorld() const;
@ -42,6 +43,7 @@ namespace Ndk
inline bool HasEntity(const Entity* entity) const; inline bool HasEntity(const Entity* entity) const;
void SetUpdateOrder(int updateOrder);
inline void SetUpdateRate(float updatePerSecond); inline void SetUpdateRate(float updatePerSecond);
inline void Update(float elapsedTime); inline void Update(float elapsedTime);
@ -93,6 +95,7 @@ namespace Ndk
bool m_updateEnabled; bool m_updateEnabled;
float m_updateCounter; float m_updateCounter;
float m_updateRate; float m_updateRate;
int m_updateOrder;
static SystemIndex s_nextIndex; static SystemIndex s_nextIndex;
}; };

View File

@ -16,7 +16,9 @@ namespace Ndk
inline BaseSystem::BaseSystem(SystemIndex systemId) : inline BaseSystem::BaseSystem(SystemIndex systemId) :
m_systemIndex(systemId), m_systemIndex(systemId),
m_updateEnabled(true) m_world(nullptr),
m_updateEnabled(true),
m_updateOrder(0)
{ {
SetUpdateRate(30); SetUpdateRate(30);
} }
@ -33,7 +35,8 @@ namespace Ndk
m_systemIndex(system.m_systemIndex), m_systemIndex(system.m_systemIndex),
m_updateEnabled(system.m_updateEnabled), m_updateEnabled(system.m_updateEnabled),
m_updateCounter(0.f), m_updateCounter(0.f),
m_updateRate(system.m_updateRate) m_updateRate(system.m_updateRate),
m_updateOrder(system.m_updateOrder)
{ {
} }
@ -69,7 +72,18 @@ namespace Ndk
} }
/*! /*!
* \brief Gets the rate of update for the system * \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 * \return Update rate
*/ */

View File

@ -24,6 +24,7 @@ namespace Ndk
class NDK_API World : public Nz::HandledObject<World> class NDK_API World : public Nz::HandledObject<World>
{ {
friend BaseSystem;
friend Entity; friend Entity;
public: public:
@ -72,6 +73,8 @@ namespace Ndk
private: private:
inline void Invalidate(); inline void Invalidate();
inline void Invalidate(EntityId id); inline void Invalidate(EntityId id);
inline void InvalidateSystemOrder();
void ReorderSystems();
struct EntityBlock struct EntityBlock
{ {
@ -87,11 +90,13 @@ namespace Ndk
}; };
std::vector<std::unique_ptr<BaseSystem>> m_systems; std::vector<std::unique_ptr<BaseSystem>> m_systems;
std::vector<BaseSystem*> m_orderedSystems;
std::vector<EntityBlock> m_entities; std::vector<EntityBlock> m_entities;
std::vector<EntityId> m_freeIdList; std::vector<EntityId> m_freeIdList;
EntityList m_aliveEntities; EntityList m_aliveEntities;
Nz::Bitset<Nz::UInt64> m_dirtyEntities; Nz::Bitset<Nz::UInt64> m_dirtyEntities;
Nz::Bitset<Nz::UInt64> m_killedEntities; Nz::Bitset<Nz::UInt64> m_killedEntities;
bool m_orderedSystemsUpdated;
}; };
} }

View File

@ -53,6 +53,7 @@ namespace Ndk
m_systems[index]->SetWorld(this); m_systems[index]->SetWorld(this);
Invalidate(); // We force an update for every entities Invalidate(); // We force an update for every entities
InvalidateSystemOrder(); // And regenerate the system update list
return *m_systems[index].get(); return *m_systems[index].get();
} }
@ -206,6 +207,8 @@ namespace Ndk
inline void World::RemoveAllSystems() inline void World::RemoveAllSystems()
{ {
m_systems.clear(); m_systems.clear();
InvalidateSystemOrder();
} }
/*! /*!
@ -219,7 +222,11 @@ namespace Ndk
inline void World::RemoveSystem(SystemIndex index) inline void World::RemoveSystem(SystemIndex index)
{ {
if (HasSystem(index)) if (HasSystem(index))
{
m_systems[index].reset(); m_systems[index].reset();
InvalidateSystemOrder();
}
} }
/*! /*!
@ -246,32 +253,11 @@ namespace Ndk
Update(); //< Update entities Update(); //< Update entities
// And then update systems // And then update systems
for (auto& systemPtr : m_systems) if (!m_orderedSystemsUpdated)
{ ReorderSystems();
if (systemPtr)
systemPtr->Update(elapsedTime);
}
}
/*! for (auto& systemPtr : m_orderedSystems)
* \brief Invalidates each entity in the world systemPtr->Update(elapsedTime);
*/
inline void World::Invalidate()
{
m_dirtyEntities.Resize(m_entities.size(), false);
m_dirtyEntities.Set(true); // Activation of all bits
}
/*!
* \brief Invalidates an entity in the world
*
* \param id Identifier of the entity
*/
inline void World::Invalidate(EntityId id)
{
m_dirtyEntities.UnboundedSet(id, true);
} }
/*! /*!
@ -281,10 +267,12 @@ namespace Ndk
inline World& World::operator=(World&& world) noexcept inline World& World::operator=(World&& world) noexcept
{ {
m_aliveEntities = std::move(world.m_aliveEntities); m_aliveEntities = std::move(world.m_aliveEntities);
m_dirtyEntities = std::move(world.m_dirtyEntities); m_dirtyEntities = std::move(world.m_dirtyEntities);
m_freeIdList = std::move(world.m_freeIdList); m_freeIdList = std::move(world.m_freeIdList);
m_killedEntities = std::move(world.m_killedEntities); m_killedEntities = std::move(world.m_killedEntities);
m_orderedSystems = std::move(world.m_orderedSystems);
m_orderedSystemsUpdated = world.m_orderedSystemsUpdated;
m_entities = std::move(world.m_entities); m_entities = std::move(world.m_entities);
for (EntityBlock& block : m_entities) for (EntityBlock& block : m_entities)
@ -296,4 +284,20 @@ namespace Ndk
return *this; return *this;
} }
inline void World::Invalidate()
{
m_dirtyEntities.Resize(m_entities.size(), false);
m_dirtyEntities.Set(true); // Activation of all bits
}
inline void World::Invalidate(EntityId id)
{
m_dirtyEntities.UnboundedSet(id, true);
}
inline void World::InvalidateSystemOrder()
{
m_orderedSystemsUpdated = false;
}
} }

View File

@ -3,6 +3,7 @@
// For conditions of distribution and use, see copyright notice in Prerequesites.hpp // For conditions of distribution and use, see copyright notice in Prerequesites.hpp
#include <NDK/BaseSystem.hpp> #include <NDK/BaseSystem.hpp>
#include <NDK/World.hpp>
namespace Ndk namespace Ndk
{ {
@ -56,6 +57,26 @@ namespace Ndk
return true; return true;
} }
/*!
* \brief Sets the update order of this system
*
* The system update order is used by the world it belongs to in order to know in which order they should be updated, as some application logic may rely a specific update order.
* A system with a greater update order (ex: 1) is guaranteed to be updated after a system with a lesser update order (ex: -1), otherwise the order is unspecified (and is not guaranteed to be stable).
*
* \param updateOrder The relative update order of the system
*
* \remark The update order is only used by World::Update(float) and does not have any effect regarding a call to BaseSystem::Update(float)
*
* \see GetUpdateOrder
*/
inline void BaseSystem::SetUpdateOrder(int updateOrder)
{
m_updateOrder = updateOrder;
if (m_world)
m_world->InvalidateSystemOrder();
}
/*! /*!
* \brief Operation to perform when entity is added to the system * \brief Operation to perform when entity is added to the system
* *

View File

@ -249,4 +249,22 @@ namespace Ndk
} }
m_dirtyEntities.Reset(); m_dirtyEntities.Reset();
} }
void World::ReorderSystems()
{
m_orderedSystems.clear();
for (auto& systemPtr : m_systems)
{
if (systemPtr)
m_orderedSystems.push_back(systemPtr.get());
}
std::sort(m_orderedSystems.begin(), m_orderedSystems.end(), [] (BaseSystem* first, BaseSystem* second)
{
return first->GetUpdateOrder() < second->GetUpdateOrder();
});
m_orderedSystemsUpdated = true;
}
} }