41#include <unordered_map>
52 template <
typename Data>
56 inline bool batchable(
const std::optional<T>& lhs,
const std::optional<T>& rhs)
58 return !!lhs == !!rhs && (lhs == std::nullopt || batchable(*lhs, *rhs));
61 template <
typename Data>
64 if (!!lhs.
ptr != !!rhs.
ptr)
66 if (lhs.
ptr ==
nullptr)
68 return batchable(*lhs.
ptr, *rhs.
ptr);
73 template <
typename Data>
82 template <
typename Data>
91 template <
typename Data>
96 typedef std::pair<const std::string, mapped_type>
value_type;
101 template <
typename Data>
106 typedef std::pair<const std::string, mapped_type>
value_type;
113 template <
typename Data>
118 template <
typename Data,
typename Base>
137 iComponentData{ aOther.iComponentData }
143 iComponentData = aRhs.iComponentData;
153 return data_meta_type::id();
167 return data_meta_type::name();
171 return data_meta_type::field_count();
175 return data_meta_type::field_type(aFieldIndex);
179 return data_meta_type::field_type_id(aFieldIndex);
183 return data_meta_type::field_name(aFieldIndex);
188 return iComponentData;
192 return iComponentData;
208 template <
typename Data>
214 using typename base_type::entity_record_not_found;
215 using typename base_type::invalid_data;
232 ++iOwner.iUsingSnapshot;
235 iOwner{ aOther.iOwner }
237 ++iOwner.iUsingSnapshot;
241 --iOwner.iUsingSnapshot;
246 return *iOwner.iSnapshot;
256 iHaveSnapshot{ false },
262 iEntities{ aOther.iEntities },
263 iReverseIndices{ aOther.iReverseIndices },
264 iHaveSnapshot{ false },
272 iEntities = aRhs.iEntities;
273 iReverseIndices = aRhs.iReverseIndices;
289 using base_type::operator[];
295 auto index = lhs - rhs;
308 return iReverseIndices;
312 return iReverseIndices;
328 throw entity_record_not_found();
339 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
344 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
349 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
354 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
359 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
362 throw entity_record_not_found();
363 if constexpr (data_meta_type::has_handles)
367 auto tailEntity =
entities().back();
375 if (ss.data().has_entity_record(aEntity))
376 ss.data().destroy_entity_record(aEntity);
381 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
382 return do_populate(aEntity, aData);
386 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
387 return do_populate(aEntity, aData);
389 const void*
populate(
entity_id aEntity,
const void* aComponentData, std::size_t aComponentDataSize)
override
391 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
393 throw invalid_data();
394 if (aComponentData !=
nullptr)
395 return &do_populate(aEntity, *
static_cast<const data_type*
>(aComponentData));
402 return iHaveSnapshot;
406 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
409 if (iSnapshot ==
nullptr)
413 iHaveSnapshot =
true;
418 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
421 template <
typename Compare>
424 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
426 [
this](
auto lhs,
auto rhs)
431 auto& lhsEntity =
entities()[lhsIndex];
432 auto& rhsEntity =
entities()[rhsIndex];
441 template <
typename Callable>
442 void apply(
const Callable& aCallable)
444 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
446 aCallable(*
this, data);
448 template <
typename Callable>
449 void parallel_apply(
const Callable& aCallable, std::size_t aMinimumParallelismCount = 0)
451 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
455 template <
typename T>
458 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
460 return do_update(aEntity, aComponentData);
486 template <
typename T>
489 std::scoped_lock<component_mutex<Data>> lock{
mutex() };
491 record = aComponentData;
497 mutable std::atomic<bool> iHaveSnapshot;
498 mutable std::atomic<uint32_t> iUsingSnapshot;
502 template <
typename Data>
523 template <
typename Data>
529 using typename base_type::entity_record_not_found;
530 using typename base_type::invalid_data;
577 if constexpr (mapped_type::meta::has_updater)
585 if constexpr (mapped_type::meta::has_updater)
589 const void*
populate(
const std::string& aName,
const void* aComponentData, std::size_t aComponentDataSize)
override
592 throw invalid_data();
593 if (aComponentData !=
nullptr)
scoped_snapshot(self_type &aOwner)
scoped_snapshot(const scoped_snapshot &aOther)
detail::crack_component_data< Data >::value_type value_type
const component_id & id() const override
const neolib::i_string & name() const override
component_base(const self_type &aOther)
bool is_data_optional() const override
value_type & operator[](typename component_data_t::size_type aIndex)
detail::crack_component_data< Data >::container_type component_data_t
component_data_t & component_data()
const neolib::i_string & field_name(uint32_t aFieldIndex) const override
self_type & operator=(const self_type &aRhs)
data_type::meta data_meta_type
component_mutex< Data > & mutex() const override
neolib::uuid field_type_id(uint32_t aFieldIndex) const override
detail::crack_component_data< Data >::data_type data_type
const component_data_t & component_data() const
component_base(i_ecs &aEcs)
uint32_t field_count() const override
i_ecs & ecs() const override
const value_type & operator[](typename component_data_t::size_type aIndex) const
component_data_field_type field_type(uint32_t aFieldIndex) const override
component_data_t::size_type reverse_index_t
entity_id entity(const value_type &aData) const
base_type::component_data_t component_data_t
reverse_index_t reverse_index(entity_id aEntity) const
component_data_entities_t & entities()
void apply(const Callable &aCallable)
std::unique_ptr< self_type > snapshot_ptr
std::vector< reverse_index_t > reverse_indices_t
value_type & entity_record_no_lock(entity_id aEntity, bool aCreate=false)
value_type & populate(entity_id aEntity, const value_type &aData)
base_type::data_type data_type
reverse_indices_t & reverse_indices()
scoped_snapshot snapshot()
base_type::value_type value_type
bool has_entity_record(entity_id aEntity) const override
void parallel_apply(const Callable &aCallable, std::size_t aMinimumParallelismCount=0)
bool have_snapshot() const
value_type & entity_record(entity_id aEntity, bool aCreate=false)
bool has_entity_record_no_lock(entity_id aEntity) const override
value_type & populate(entity_id aEntity, value_type &&aData)
const reverse_indices_t & reverse_indices() const
void destroy_entity_record(entity_id aEntity) override
void sort(Compare aComparator)
std::vector< entity_id > component_data_entities_t
component(const self_type &aOther)
const void * populate(entity_id aEntity, const void *aComponentData, std::size_t aComponentDataSize) override
const value_type & entity_record_no_lock(entity_id aEntity) const
const component_data_entities_t & entities() const
base_type::data_meta_type data_meta_type
const value_type & entity_record(entity_id aEntity) const
self_type & operator=(const self_type &aRhs)
reverse_index_t reverse_index_no_lock(entity_id aEntity) const
const mapped_type & operator[](typename component_data_t::size_type aIndex) const
mapped_type & operator[](const std::string &aName)
const void * populate(const std::string &aName, const void *aComponentData, std::size_t aComponentDataSize) override
base_type::component_data_t component_data_t
component_data_t::mapped_type mapped_type
base_type::data_type data_type
shared_component(i_ecs &aEcs)
const mapped_type & operator[](const std::string &aName) const
base_type::value_type value_type
shared< mapped_type > populate(const std::string &aName, mapped_type &&aData)
shared< mapped_type > populate(const std::string &aName, const mapped_type &aData)
base_type::data_meta_type data_meta_type
mapped_type & operator[](typename component_data_t::size_type aIndex)
basic_size< coordinate > size
constexpr entity_id null_entity
component_data_field_type
std::remove_cv_t< std::remove_reference_t< _Ty > > ecs_data_type_t
to_const_reference_t< T > to_const(T &&object)
void intrusive_sort(RandomIt first, RandomIt last, Swapper swapper, Compare comp)
void parallel_apply(thread_pool &aThreadPool, Container &aContainer, std::function< void(typename Container::value_type &aElement)> aFunction, std::size_t aMinimumParallelismCount=0)
void swap(plf::hive< element_type, allocator_type > &a, plf::hive< element_type, allocator_type > &b) noexcept(std::allocator_traits< allocator_type >::propagate_on_container_swap::value||std::allocator_traits< allocator_type >::is_always_equal::value)
it_type next(it_type it, const typename iterator_traits< it_type >::difference_type distance=1)
entity_record_not_found()
std::pair< const std::string, mapped_type > value_type
ecs_data_type_t< Data > data_type
std::unordered_map< std::string, mapped_type > container_type
std::pair< const std::string, mapped_type > value_type
std::unordered_map< std::string, mapped_type > container_type
std::optional< data_type > mapped_type
ecs_data_type_t< Data > data_type
std::vector< value_type > container_type
ecs_data_type_t< Data > data_type
std::optional< data_type > value_type
ecs_data_type_t< Data > data_type
std::vector< value_type > container_type
shared(const mapped_type *aData)
detail::crack_component_data< shared< Data > >::mapped_type mapped_type
shared(const mapped_type &aData)