39#include <unordered_map>
66 return static_cast<ecs_flags>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
71 return static_cast<ecs_flags>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
76 return aLhs =
static_cast<ecs_flags>(
static_cast<uint32_t
>(aLhs) |
static_cast<uint32_t
>(aRhs));
81 return aLhs =
static_cast<ecs_flags>(
static_cast<uint32_t
>(aLhs) &
static_cast<uint32_t
>(aRhs));
96 struct uuid_exists : std::runtime_error {
uuid_exists(
const std::string& aContext) : std::runtime_error(
"i_ecs::uuid_exists: " + aContext) {} };
186 template <
typename ComponentData,
typename... ComponentDataRest>
189 populate(aEntity, std::forward<ComponentData>(aComponentData));
190 populate(aEntity, std::forward<ComponentDataRest>(aComponentDataRest)...);
192 template <
typename ComponentData>
197 template <
typename ComponentData,
typename... ComponentDataRest>
201 populate_shared(aName, std::forward<ComponentDataRest>(aComponentDataRest)...);
203 template <
typename ComponentData>
208 template <
typename ComponentData>
213 template <
typename ComponentData>
218 template <
typename ComponentData>
222 register_component<ecs_data_type_t<ComponentData>>();
225 template <
typename ComponentData>
230 template <
typename ComponentData>
235 template <
typename ComponentData>
239 register_shared_component<ecs_data_type_t<ComponentData>>();
242 template <
typename System>
247 template <
typename System>
252 template <
typename System>
256 register_system<ecs_data_type_t<System>>();
260 template <
typename ComponentData>
265 template <
typename ComponentData>
270 template <
typename ComponentData>
275 template <
typename ComponentData>
280 template <
typename System>
285 template <
typename System>
290 [&]() {
return std::unique_ptr<i_system>{std::make_unique<ecs_data_type_t<System>>(*this)}; });
293 template <
typename Handle>
296 return reinterpret_cast<Handle
>(
to_handle(aId));
298 template <
typename Context,
typename Handle>
303 template <
typename Context,
typename Handle>
306 if constexpr(std::is_pointer<Handle>::value)
307 return reinterpret_cast<Handle
>(
update_handle(aId,
typeid(Context),
reinterpret_cast<handle_t>(aHandle)));
309 return static_cast<Handle
>(
reinterpret_cast<intptr_t
>(
update_handle(aId,
typeid(Context),
reinterpret_cast<handle_t>(aHandle))));
311 template <
typename Handle>
314 if constexpr(std::is_pointer<Handle>::value)
317 return static_cast<Handle
>(
reinterpret_cast<intptr_t
>(
release_handle(aId)));
321 template <
typename Data>
333 std::scoped_lock<neolib::i_lockable> iLock;
338 template <
typename... Data>
342 template <
typename T,
typename>
343 static T fwd(T o) {
return o; }
344 template <
typename Data2>
348 struct not_linked : std::logic_error {
not_linked() : std::logic_error{
"neolib::neolib::ecs::scoped_component_lock::proxy_mutex::not_linked"} {} };
350 proxy_mutex(
const i_ecs& aEcs) :
354 proxy_mutex(
i_ecs& aEcs) :
359 void lock() noexcept
override
364 void unlock() noexcept
override
369 bool try_lock() noexcept
override
372 return subject().try_lock();
377 i_lockable& subject()
386 return iSubject !=
nullptr;
392 auto& link = *iSubject;
399 i_lockable* iSubject;
403 iProxies{ fwd<const
i_ecs&, Data>(aEcs)... }
408 iProxies{ fwd<
i_ecs&, Data>(aEcs)... }
413 iProxies{ fwd<const
i_ecs&, Data>(aEcs)... }
415 iDontUnlock.emplace();
418 iProxies{ fwd<
i_ecs&, Data>(aEcs)... }
420 iDontUnlock.emplace();
430 if constexpr (
sizeof...(Data) >= 2)
431 std::lock(
std::get<index_of_v<Data, Data...>>(iProxies)...);
432 else if constexpr (
sizeof...(Data) == 1)
433 std::get<0>(iProxies).lock();
441 if constexpr (
sizeof...(Data) >= 2)
442 return std::try_lock(
std::get<index_of_v<Data, Data...>>(iProxies)...) == -1;
443 else if constexpr (
sizeof...(Data) == 1)
444 return std::get<0>(iProxies).try_lock();
447 template <
typename Data2>
452 template <
typename Data2>
457 template <
typename... Data2>
460 (lock_if_impl<Data2>(), ...);
462 template <
typename... Data2>
465 (unlock_if_impl<Data2>(), ...);
468 template <
typename Data2>
471 if (controlling<Data2>())
472 mutex<Data2>().lock();
474 template <
typename Data2>
475 void unlock_if_impl()
477 if (controlling<Data2>())
478 mutex<Data2>().unlock();
481 std::tuple<proxy_mutex<Data>...> iProxies;
482 std::optional<dont_lock_t> iDontUnlock;
490 populate(newEntity, std::forward<ComponentData>(aComponentData)...);
500 return create_entity(aArchetype.id(), std::forward<ComponentData>(aComponentData)...);
506 auto creator = [=,
this]()
516 auto creator = [=,
this, &aArchetype]()
std::function< std::unique_ptr< i_component >()> component_factory
virtual const system_factories_t & system_factories() const =0
const ecs_data_type_t< System > & system() const
Handle update_handle(handle_id aId, Handle aHandle)
virtual bool run_threaded(const system_id &aSystemId) const =0
virtual ecs_flags flags() const =0
virtual const components_t & components() const =0
virtual i_component & component(component_id aComponentId)=0
virtual const i_component & component(component_id aComponentId) const =0
virtual const component_factories_t & component_factories() const =0
void register_shared_component()
virtual const shared_component_factories_t & shared_component_factories() const =0
virtual shared_component_factories_t & shared_component_factories()=0
virtual bool shared_component_instantiated(component_id aComponentId) const =0
bool component_instantiated() const
virtual const i_shared_component & shared_component(component_id aComponentId) const =0
virtual systems_t & systems()=0
Handle to_handle(handle_id aId) const
virtual void commit_async_entity_creation()=0
void register_component()
std::unordered_map< component_id, std::unique_ptr< i_component >, quick_uuid_hash > components_t
std::unordered_map< component_id, component_factory, quick_uuid_hash > component_factories_t
virtual void async_create_entity(const std::function< void()> &aCreator)=0
virtual components_t & components()=0
virtual void register_shared_component(component_id aComponentId, shared_component_factory aFactory)=0
const neolib::ecs::shared_component< ComponentData > & shared_component() const
neolib::ecs::shared_component< ComponentData > & shared_component()
virtual bool system_instantiated(system_id aSystemId) const =0
std::function< std::unique_ptr< i_shared_component >()> shared_component_factory
virtual component_factories_t & component_factories()=0
Handle release_handle(handle_id aId)
virtual void async_destroy_entity(entity_id aEntityId, bool aNotify=true)=0
std::function< std::unique_ptr< i_system >()> system_factory
virtual handle_t update_handle(handle_id aId, const std::type_info &aTypeInfo, handle_t aHandle)=0
virtual i_system & system(system_id aSystemId)=0
handle_id add_handle(Handle aHandle)
std::unordered_map< component_id, shared_component_factory, quick_uuid_hash > shared_component_factories_t
bool component_registered() const
virtual neolib::i_lockable & mutex() const =0
virtual void register_archetype(const i_entity_archetype &aArchetype)=0
virtual entity_id create_entity(const entity_archetype_id &aArchetypeId)=0
virtual shared_components_t & shared_components()=0
virtual const systems_t & systems() const =0
virtual void resume_all_systems()=0
virtual handle_t to_handle(handle_id aId) const =0
virtual bool shared_component_registered(component_id aComponentId) const =0
virtual bool component_registered(component_id aComponentId) const =0
virtual const i_system & system(system_id aSystemId) const =0
virtual neolib::thread_pool & thread_pool() const =0
virtual void pause_all_systems()=0
virtual void commit_async_entity_destruction()=0
declare_event(systems_paused) declare_event(systems_resumed) declare_event(entity_created
virtual void free_entity_id(entity_id aId)=0
virtual bool all_systems_paused() const =0
virtual const shared_components_t & shared_components() const =0
virtual void register_system(system_id aSystemId, system_factory aFactory)=0
virtual void destroy_entity(entity_id aEntityId, bool aNotify=true)=0
virtual archetype_registry_t & archetypes()=0
virtual const i_entity_archetype & archetype(entity_archetype_id aArchetypeId) const =0
std::unordered_map< component_id, std::unique_ptr< i_shared_component >, quick_uuid_hash > shared_components_t
bool shared_component_instantiated() const
std::unordered_map< system_id, system_factory, quick_uuid_hash > system_factories_t
virtual handle_t release_handle(handle_id aId)=0
void populate_shared(const std::string &aName, ComponentData &&aComponentData)
bool shared_component_registered() const
neolib::ecs::component< ComponentData > & component()
ecs_data_type_t< System > & system()
virtual i_shared_component & shared_component(component_id aComponentId)=0
virtual bool archetype_registered(const i_entity_archetype &aArchetype) const =0
void populate(entity_id aEntity, ComponentData &&aComponentData, ComponentDataRest &&... aComponentDataRest)
virtual const archetype_registry_t & archetypes() const =0
virtual bool component_instantiated(component_id aComponentId) const =0
std::unordered_map< system_id, std::unique_ptr< i_system >, quick_uuid_hash > systems_t
void populate(entity_id aEntity, ComponentData &&aComponentData)
bool system_instantiated() const
virtual i_entity_archetype & archetype(entity_archetype_id aArchetypeId)=0
std::unordered_map< entity_archetype_id, std::shared_ptr< const i_entity_archetype >, quick_uuid_hash > archetype_registry_t
virtual bool system_registered(system_id aSystemId) const =0
virtual void register_archetype(std::shared_ptr< const i_entity_archetype > aArchetype)=0
virtual void register_component(component_id aComponentId, component_factory aFactory)=0
virtual entity_id next_entity_id()=0
virtual handle_id add_handle(const std::type_info &aTypeInfo, handle_t aHandle)=0
bool system_registered() const
void populate_shared(const std::string &aName, ComponentData &&aComponentData, ComponentDataRest &&... aComponentDataRest)
virtual system_factories_t & system_factories()=0
const neolib::ecs::component< ComponentData > & component() const
virtual void populate_default_components(i_ecs &aEcs, entity_id aEntity)=0
scoped_component_lock(i_ecs &aEcs, dont_lock_t)
scoped_component_lock(const i_ecs &aEcs, dont_lock_t)
scoped_component_lock(i_ecs &aEcs)
scoped_component_lock(const i_ecs &aEcs)
~shared_component_scoped_lock()
shared_component_scoped_lock(const i_ecs &aEcs)
constexpr component_data_field_type & operator&=(component_data_field_type &aLhs, component_data_field_type aRhs)
const struct neolib::ecs::dont_lock_t dont_lock
constexpr component_data_field_type operator&(component_data_field_type aLhs, component_data_field_type aRhs)
constexpr component_data_field_type & operator|=(component_data_field_type &aLhs, component_data_field_type aRhs)
constexpr component_data_field_type operator|(component_data_field_type aLhs, component_data_field_type aRhs)
std::remove_cv_t< std::remove_reference_t< _Ty > > ecs_data_type_t
constexpr std::size_t index_of_v
to_const_reference_t< T > to_const(T &&object)
constexpr T & get(neolib::variant< Types... > &var)
#define declare_event(declName,...)
entity_archetype_not_found()
uuid_exists(const std::string &aContext)
virtual void lock() noexcept=0