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

View File

@ -16,7 +16,9 @@ namespace Ndk
inline BaseSystem::BaseSystem(SystemIndex systemId) :
m_systemIndex(systemId),
m_updateEnabled(true)
m_world(nullptr),
m_updateEnabled(true),
m_updateOrder(0)
{
SetUpdateRate(30);
}
@ -33,7 +35,8 @@ namespace Ndk
m_systemIndex(system.m_systemIndex),
m_updateEnabled(system.m_updateEnabled),
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
*/

View File

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

View File

@ -53,6 +53,7 @@ namespace Ndk
m_systems[index]->SetWorld(this);
Invalidate(); // We force an update for every entities
InvalidateSystemOrder(); // And regenerate the system update list
return *m_systems[index].get();
}
@ -206,6 +207,8 @@ namespace Ndk
inline void World::RemoveAllSystems()
{
m_systems.clear();
InvalidateSystemOrder();
}
/*!
@ -219,7 +222,11 @@ namespace Ndk
inline void World::RemoveSystem(SystemIndex index)
{
if (HasSystem(index))
{
m_systems[index].reset();
InvalidateSystemOrder();
}
}
/*!
@ -246,32 +253,11 @@ namespace Ndk
Update(); //< Update entities
// And then update systems
for (auto& systemPtr : m_systems)
{
if (systemPtr)
systemPtr->Update(elapsedTime);
}
}
if (!m_orderedSystemsUpdated)
ReorderSystems();
/*!
* \brief Invalidates each entity in the world
*/
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);
for (auto& systemPtr : m_orderedSystems)
systemPtr->Update(elapsedTime);
}
/*!
@ -281,10 +267,12 @@ namespace Ndk
inline World& World::operator=(World&& world) noexcept
{
m_aliveEntities = std::move(world.m_aliveEntities);
m_dirtyEntities = std::move(world.m_dirtyEntities);
m_freeIdList = std::move(world.m_freeIdList);
m_killedEntities = std::move(world.m_killedEntities);
m_aliveEntities = std::move(world.m_aliveEntities);
m_dirtyEntities = std::move(world.m_dirtyEntities);
m_freeIdList = std::move(world.m_freeIdList);
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);
for (EntityBlock& block : m_entities)
@ -296,4 +284,20 @@ namespace Ndk
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
#include <NDK/BaseSystem.hpp>
#include <NDK/World.hpp>
namespace Ndk
{
@ -56,6 +57,26 @@ namespace Ndk
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
*

View File

@ -249,4 +249,22 @@ namespace Ndk
}
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;
}
}