Remove component bitsets from ecs; use uuid hash tables instead
This commit is contained in:
parent
809a0ec212
commit
31ffd4dc54
10 changed files with 202 additions and 124 deletions
18
libs/ecs/include/psemek/ecs/detail/component_hash.hpp
Normal file
18
libs/ecs/include/psemek/ecs/detail/component_hash.hpp
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/uuid.hpp>
|
||||||
|
#include <psemek/util/span.hpp>
|
||||||
|
#include <psemek/util/hash.hpp>
|
||||||
|
|
||||||
|
namespace psemek::ecs::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
inline std::size_t component_hash(util::span<util::uuid const> const & uuids)
|
||||||
|
{
|
||||||
|
std::size_t result = 0xcd5694d2b3f3443eull;
|
||||||
|
for (auto const & uuid : uuids)
|
||||||
|
result ^= std::hash<util::uuid>{}(uuid);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <psemek/ecs/detail/component_mask.hpp>
|
|
||||||
#include <psemek/util/uuid.hpp>
|
|
||||||
#include <psemek/util/span.hpp>
|
|
||||||
#include <psemek/util/unique_sequential_storage.hpp>
|
|
||||||
|
|
||||||
namespace psemek::ecs::detail
|
|
||||||
{
|
|
||||||
|
|
||||||
template <typename ... Components>
|
|
||||||
struct component_uuid_holder
|
|
||||||
{
|
|
||||||
util::uuid uuids[sizeof...(Components)] { Components::uuid() ... };
|
|
||||||
|
|
||||||
auto get() const
|
|
||||||
{
|
|
||||||
return util::span<util::uuid const>(uuids);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct component_uuid_holder<>
|
|
||||||
{
|
|
||||||
auto get() const
|
|
||||||
{
|
|
||||||
return util::span<util::uuid const>();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct component_index
|
|
||||||
{
|
|
||||||
template <typename ... UUIDS>
|
|
||||||
component_mask make_component_mask(UUIDS const & ... uuids)
|
|
||||||
{
|
|
||||||
component_mask result;
|
|
||||||
(result.set(storage_.insert(uuids), true), ...);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
component_mask make_component_mask(util::span<util::uuid const> uuids)
|
|
||||||
{
|
|
||||||
component_mask result;
|
|
||||||
for (util::uuid const & uuid : uuids)
|
|
||||||
result.set(storage_.insert(uuid), true);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
util::unique_sequential_storage<util::uuid> storage_;
|
|
||||||
};
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <psemek/util/dynamic_bitset.hpp>
|
|
||||||
|
|
||||||
namespace psemek::ecs::detail
|
|
||||||
{
|
|
||||||
|
|
||||||
using component_mask = util::dynamic_bitset;
|
|
||||||
|
|
||||||
}
|
|
||||||
29
libs/ecs/include/psemek/ecs/detail/component_uuid_helper.hpp
Normal file
29
libs/ecs/include/psemek/ecs/detail/component_uuid_helper.hpp
Normal file
|
|
@ -0,0 +1,29 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <psemek/util/uuid.hpp>
|
||||||
|
#include <psemek/util/span.hpp>
|
||||||
|
|
||||||
|
namespace psemek::ecs::detail
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename ... Components>
|
||||||
|
struct component_uuid_helper
|
||||||
|
{
|
||||||
|
util::uuid uuids[sizeof...(Components)] { Components::uuid() ... };
|
||||||
|
|
||||||
|
auto get() const
|
||||||
|
{
|
||||||
|
return util::span<util::uuid const>(uuids);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct component_uuid_helper<>
|
||||||
|
{
|
||||||
|
auto get() const
|
||||||
|
{
|
||||||
|
return util::span<util::uuid const>();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,50 +1,104 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/ecs/detail/query_cache.hpp>
|
#include <psemek/ecs/detail/query_cache.hpp>
|
||||||
#include <psemek/ecs/detail/component_mask.hpp>
|
#include <psemek/ecs/detail/component_hash.hpp>
|
||||||
|
#include <psemek/util/hash_table.hpp>
|
||||||
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace psemek::ecs::detail
|
namespace psemek::ecs::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct query_cache_set
|
||||||
|
{
|
||||||
|
std::size_t hash;
|
||||||
|
util::hash_set<util::uuid> uuids;
|
||||||
|
std::vector<std::weak_ptr<query_cache>> caches;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_cache_hash
|
||||||
|
{
|
||||||
|
std::size_t operator()(util::span<util::uuid const> const & uuids) const
|
||||||
|
{
|
||||||
|
return component_hash(uuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t operator()(std::unique_ptr<query_cache_set> const & set) const
|
||||||
|
{
|
||||||
|
return set->hash;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct query_cache_equal
|
||||||
|
{
|
||||||
|
bool operator()(util::span<util::uuid const> const & uuids, std::unique_ptr<query_cache_set> const & set) const
|
||||||
|
{
|
||||||
|
if (uuids.size() != set->uuids.size())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (auto const & uuid : uuids)
|
||||||
|
if (!set->uuids.contains(uuid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(std::unique_ptr<query_cache_set> const & set1, std::unique_ptr<query_cache_set> const & set2) const
|
||||||
|
{
|
||||||
|
return set1.get() == set2.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: store query caches in a bitmask trie balanced by subtree size
|
// TODO: store query caches in a bitmask trie balanced by subtree size
|
||||||
struct query_cache_container
|
struct query_cache_container
|
||||||
{
|
{
|
||||||
std::shared_ptr<query_cache> create(component_mask const & mask, util::span<util::uuid const> component_uuids)
|
std::shared_ptr<query_cache> create(util::span<util::uuid const> component_uuids)
|
||||||
{
|
{
|
||||||
auto result = std::make_shared<query_cache>();
|
auto result = std::make_shared<query_cache>();
|
||||||
result->component_uuids.assign(component_uuids.begin(), component_uuids.end());
|
result->component_uuids.assign(component_uuids.begin(), component_uuids.end());
|
||||||
get(mask).emplace_back(result);
|
auto it = caches_.find(component_uuids);
|
||||||
|
if (it == caches_.end())
|
||||||
|
{
|
||||||
|
auto value = std::make_unique<query_cache_set>();
|
||||||
|
for (auto const & uuid : component_uuids)
|
||||||
|
value->uuids.insert(uuid);
|
||||||
|
value->hash = component_hash(component_uuids);
|
||||||
|
it = caches_.insert(std::move(value)).first;
|
||||||
|
}
|
||||||
|
it->get()->caches.push_back(result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function, typename ContainsUUID>
|
||||||
void apply(Function && function, component_mask const & mask)
|
void apply(Function && function, ContainsUUID && contains_uuid)
|
||||||
{
|
{
|
||||||
for (auto & caches : caches_)
|
for (auto & cache_set : caches_)
|
||||||
{
|
{
|
||||||
if (!util::is_subset(caches.first, mask)) continue;
|
bool good = true;
|
||||||
filter(caches.second);
|
for (auto const & uuid : cache_set->uuids)
|
||||||
for (auto & cache : caches.second)
|
if (!contains_uuid(uuid))
|
||||||
|
{
|
||||||
|
good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!good)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
filter(cache_set->caches);
|
||||||
|
for (auto & cache : cache_set->caches)
|
||||||
function(*cache.lock());
|
function(*cache.lock());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<component_mask, std::vector<std::weak_ptr<query_cache>>> caches_;
|
util::hash_set<std::unique_ptr<query_cache_set>, query_cache_hash, query_cache_equal> caches_;
|
||||||
|
|
||||||
static void filter(std::vector<std::weak_ptr<query_cache>> & caches)
|
static void filter(std::vector<std::weak_ptr<query_cache>> & caches)
|
||||||
{
|
{
|
||||||
caches.erase(std::remove_if(caches.begin(), caches.end(), [](std::weak_ptr<query_cache> const & weak){ return !weak.lock(); }), caches.end());
|
caches.erase(std::remove_if(caches.begin(), caches.end(), [](std::weak_ptr<query_cache> const & weak){ return !weak.lock(); }), caches.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::weak_ptr<query_cache>> & get(component_mask const & mask)
|
|
||||||
{
|
|
||||||
auto & result = caches_[mask];
|
|
||||||
filter(result);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
#include <psemek/ecs/entity_handle.hpp>
|
#include <psemek/ecs/entity_handle.hpp>
|
||||||
#include <psemek/ecs/detail/stride.hpp>
|
#include <psemek/ecs/detail/stride.hpp>
|
||||||
|
#include <psemek/ecs/detail/component_hash.hpp>
|
||||||
#include <psemek/util/uuid.hpp>
|
#include <psemek/util/uuid.hpp>
|
||||||
#include <psemek/util/span.hpp>
|
#include <psemek/util/span.hpp>
|
||||||
#include <psemek/util/hash_table.hpp>
|
#include <psemek/util/hash_table.hpp>
|
||||||
|
|
@ -28,31 +29,31 @@ namespace psemek::ecs::detail
|
||||||
std::size_t current_row = 0;
|
std::size_t current_row = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
util::span<util::uuid const> get_component_uuids() const
|
std::size_t hash() const
|
||||||
{
|
{
|
||||||
return component_uuids_;
|
return hash_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::size_t> get_component_column(util::uuid const & uuid) const
|
std::optional<std::size_t> component_column(util::uuid const & uuid) const
|
||||||
{
|
{
|
||||||
if (auto it = component_uuid_to_column_.find(uuid); it != component_uuid_to_column_.end())
|
if (auto it = component_uuid_to_column_.find(uuid); it != component_uuid_to_column_.end())
|
||||||
return it->second;
|
return it->second;
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::span<component_pointer const> get_component_pointers() const
|
util::span<component_pointer const> component_pointers() const
|
||||||
{
|
{
|
||||||
return component_pointers_;
|
return component_pointers_;
|
||||||
}
|
}
|
||||||
|
|
||||||
util::span<entity_handle const> get_entity_handles() const
|
util::span<entity_handle const> entity_handles() const
|
||||||
{
|
{
|
||||||
return entity_handles_;
|
return entity_handles_;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t component_count() const
|
std::size_t component_count() const
|
||||||
{
|
{
|
||||||
return component_uuids_.size();
|
return component_pointers_.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::size_t row_count() const
|
std::size_t row_count() const
|
||||||
|
|
@ -93,6 +94,7 @@ namespace psemek::ecs::detail
|
||||||
virtual ~table() = default;
|
virtual ~table() = default;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
std::size_t hash_;
|
||||||
std::vector<util::uuid> component_uuids_;
|
std::vector<util::uuid> component_uuids_;
|
||||||
util::hash_map<util::uuid, std::size_t> component_uuid_to_column_;
|
util::hash_map<util::uuid, std::size_t> component_uuid_to_column_;
|
||||||
std::vector<component_pointer> component_pointers_;
|
std::vector<component_pointer> component_pointers_;
|
||||||
|
|
@ -137,10 +139,11 @@ namespace psemek::ecs::detail
|
||||||
table_impl<Components...>::table_impl(util::span<util::uuid const> component_uuids)
|
table_impl<Components...>::table_impl(util::span<util::uuid const> component_uuids)
|
||||||
{
|
{
|
||||||
assert(sizeof...(Components) == component_uuids.size());
|
assert(sizeof...(Components) == component_uuids.size());
|
||||||
|
hash_ = component_hash(component_uuids);
|
||||||
component_uuids_.assign(component_uuids.begin(), component_uuids.end());
|
component_uuids_.assign(component_uuids.begin(), component_uuids.end());
|
||||||
component_pointers_.resize(sizeof...(Components));
|
component_pointers_.resize(sizeof...(Components));
|
||||||
for (std::size_t i = 0; i < component_uuids_.size(); ++i)
|
for (std::size_t i = 0; i < component_uuids.size(); ++i)
|
||||||
component_uuid_to_column_.insert({component_uuids_[i], i});
|
component_uuid_to_column_.insert({component_uuids[i], i});
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
|
|
|
||||||
|
|
@ -1,46 +1,85 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/ecs/detail/component_mask.hpp>
|
#include <psemek/ecs/detail/component_hash.hpp>
|
||||||
#include <psemek/ecs/detail/table.hpp>
|
#include <psemek/ecs/detail/table.hpp>
|
||||||
|
#include <psemek/util/hash_table.hpp>
|
||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace psemek::ecs::detail
|
namespace psemek::ecs::detail
|
||||||
{
|
{
|
||||||
|
|
||||||
|
struct table_hashset_hash
|
||||||
|
{
|
||||||
|
std::size_t operator()(util::span<util::uuid const> const & uuids) const
|
||||||
|
{
|
||||||
|
return component_hash(uuids);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t operator()(std::unique_ptr<table> const & table) const
|
||||||
|
{
|
||||||
|
return table->hash();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct table_hashset_equal
|
||||||
|
{
|
||||||
|
bool operator()(util::span<util::uuid const> const & uuids, std::unique_ptr<table> const & table) const
|
||||||
|
{
|
||||||
|
if (uuids.size() != table->component_count())
|
||||||
|
return false;
|
||||||
|
for (auto const & uuid : uuids)
|
||||||
|
if (!table->component_column(uuid))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator()(std::unique_ptr<table> const & table1, std::unique_ptr<table> const & table2) const
|
||||||
|
{
|
||||||
|
return table1.get() == table2.get();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: store tables in a bitmask trie balanced by subtree size
|
// TODO: store tables in a bitmask trie balanced by subtree size
|
||||||
struct table_container
|
struct table_container
|
||||||
{
|
{
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
std::pair<table *, bool> insert(component_mask const & mask, util::span<util::uuid const> component_uuids);
|
std::pair<table *, bool> insert(util::span<util::uuid const> component_uuids);
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void apply(Function && function, component_mask const & mask);
|
void apply(Function && function, util::span<util::uuid const> component_uuids);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::unordered_map<component_mask, std::unique_ptr<table>> tables_;
|
util::hash_set<std::unique_ptr<table>, table_hashset_hash, table_hashset_equal> tables_;
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
std::pair<table *, bool> table_container::insert(component_mask const & mask, util::span<util::uuid const> component_uuids)
|
std::pair<table *, bool> table_container::insert(util::span<util::uuid const> component_uuids)
|
||||||
{
|
{
|
||||||
auto & result = tables_[mask];
|
auto it = tables_.find(component_uuids);
|
||||||
bool created = false;
|
if (it != tables_.end())
|
||||||
if (!result)
|
return {it->get(), false};
|
||||||
{
|
|
||||||
result = std::make_unique<table_impl<Components...>>(component_uuids);
|
auto table = std::make_unique<table_impl<Components...>>(component_uuids);
|
||||||
created = true;
|
auto result = table.get();
|
||||||
}
|
tables_.insert(std::move(table));
|
||||||
return {result.get(), created};
|
return {result, true};
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Function>
|
template <typename Function>
|
||||||
void table_container::apply(Function && function, component_mask const & mask)
|
void table_container::apply(Function && function, util::span<util::uuid const> component_uuids)
|
||||||
{
|
{
|
||||||
for (auto & table : tables_)
|
for (auto & table : tables_)
|
||||||
{
|
{
|
||||||
if (!util::is_subset(mask, table.first)) continue;
|
bool good = true;
|
||||||
function(*table.second);
|
for (auto const & uuid : component_uuids)
|
||||||
|
if (!table->component_column(uuid))
|
||||||
|
{
|
||||||
|
good = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (good) function(*table);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <psemek/ecs/detail/component_index.hpp>
|
|
||||||
#include <psemek/ecs/detail/entity_list.hpp>
|
#include <psemek/ecs/detail/entity_list.hpp>
|
||||||
#include <psemek/ecs/detail/table_container.hpp>
|
#include <psemek/ecs/detail/table_container.hpp>
|
||||||
#include <psemek/ecs/detail/query_cache_container.hpp>
|
#include <psemek/ecs/detail/query_cache_container.hpp>
|
||||||
#include <psemek/ecs/detail/apply_helper.hpp>
|
#include <psemek/ecs/detail/apply_helper.hpp>
|
||||||
#include <psemek/ecs/detail/all_different_types.hpp>
|
#include <psemek/ecs/detail/all_different_types.hpp>
|
||||||
|
#include <psemek/ecs/detail/component_uuid_helper.hpp>
|
||||||
#include <psemek/util/span.hpp>
|
#include <psemek/util/span.hpp>
|
||||||
#include <psemek/util/range.hpp>
|
#include <psemek/util/range.hpp>
|
||||||
#include <psemek/util/exception.hpp>
|
#include <psemek/util/exception.hpp>
|
||||||
|
|
@ -164,7 +164,7 @@ namespace psemek::ecs
|
||||||
* types, the behavior is undefined.
|
* types, the behavior is undefined.
|
||||||
* If the function accesses passed components after destroying the
|
* If the function accesses passed components after destroying the
|
||||||
* currently visited entity, the behavior is undefined.
|
* currently visited entity, the behavior is undefined.
|
||||||
* If the function recursively calls `apply()`, the behavior is undefined.
|
* If the function recursively calls `apply()` or `batch_apply()`, the behavior is undefined.
|
||||||
*/
|
*/
|
||||||
template <typename ... Components, typename Function>
|
template <typename ... Components, typename Function>
|
||||||
void apply(Function && function, query_cache cache = {});
|
void apply(Function && function, query_cache cache = {});
|
||||||
|
|
@ -182,13 +182,13 @@ namespace psemek::ecs
|
||||||
* If the query cache wasn't created with the exact sequence of component
|
* If the query cache wasn't created with the exact sequence of component
|
||||||
* types, the behavior is undefined.
|
* types, the behavior is undefined.
|
||||||
* If the function creates or destroyes entities, the behavior is undefined.
|
* If the function creates or destroyes entities, the behavior is undefined.
|
||||||
|
* If the function recursively calls `apply()` or `batch_apply()`, the behavior is undefined.
|
||||||
*/
|
*/
|
||||||
template <typename ... Components, typename Function>
|
template <typename ... Components, typename Function>
|
||||||
void batch_apply(Function && function, query_cache cache = {});
|
void batch_apply(Function && function, query_cache cache = {});
|
||||||
|
|
||||||
private:
|
private:
|
||||||
detail::entity_list entity_list_;
|
detail::entity_list entity_list_;
|
||||||
mutable detail::component_index component_index_;
|
|
||||||
detail::table_container table_container_;
|
detail::table_container table_container_;
|
||||||
detail::query_cache_container query_cache_container_;
|
detail::query_cache_container query_cache_container_;
|
||||||
|
|
||||||
|
|
@ -200,10 +200,9 @@ namespace psemek::ecs
|
||||||
{
|
{
|
||||||
static_assert(detail::all_different_types_v<Components...>, "all component types must be different");
|
static_assert(detail::all_different_types_v<Components...>, "all component types must be different");
|
||||||
|
|
||||||
detail::component_uuid_holder<Components...> uuids;
|
detail::component_uuid_helper<Components...> uuids;
|
||||||
detail::component_mask mask = component_index_.make_component_mask(uuids.get());
|
|
||||||
|
|
||||||
auto insert_result = table_container_.insert<Components...>(mask, uuids.get());
|
auto insert_result = table_container_.insert<Components...>(uuids.get());
|
||||||
auto table = insert_result.first;
|
auto table = insert_result.first;
|
||||||
bool created = insert_result.second;
|
bool created = insert_result.second;
|
||||||
|
|
||||||
|
|
@ -211,7 +210,7 @@ namespace psemek::ecs
|
||||||
{
|
{
|
||||||
query_cache_container_.apply([table](detail::query_cache & cache){
|
query_cache_container_.apply([table](detail::query_cache & cache){
|
||||||
cache.add(table);
|
cache.add(table);
|
||||||
}, mask);
|
}, [table](util::uuid const & uuid){ return table->component_column(uuid) != std::nullopt; });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (table->get_iteration_data())
|
if (table->get_iteration_data())
|
||||||
|
|
@ -230,14 +229,13 @@ namespace psemek::ecs
|
||||||
template <typename ... Components>
|
template <typename ... Components>
|
||||||
query_cache entity_container::cache()
|
query_cache entity_container::cache()
|
||||||
{
|
{
|
||||||
detail::component_uuid_holder<Components...> uuids;
|
detail::component_uuid_helper<Components...> uuids;
|
||||||
detail::component_mask mask = component_index_.make_component_mask(uuids.get());
|
|
||||||
|
|
||||||
auto result = query_cache_container_.create(mask, uuids.get());
|
auto result = query_cache_container_.create(uuids.get());
|
||||||
|
|
||||||
table_container_.apply([&](detail::table & table){
|
table_container_.apply([&](detail::table & table){
|
||||||
result->add(&table);
|
result->add(&table);
|
||||||
}, mask);
|
}, uuids.get());
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
@ -252,10 +250,10 @@ namespace psemek::ecs
|
||||||
{
|
{
|
||||||
auto & iteration_data = entry.table->get_iteration_data();
|
auto & iteration_data = entry.table->get_iteration_data();
|
||||||
iteration_data.emplace();
|
iteration_data.emplace();
|
||||||
detail::static_apply_helper<Components...> apply_helper(*this, entry.table->get_entity_handles());
|
detail::static_apply_helper<Components...> apply_helper(*this, entry.table->entity_handles());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < sizeof...(Components); ++i)
|
for (std::size_t i = 0; i < sizeof...(Components); ++i)
|
||||||
apply_helper.pointers[i] = entry.table->get_component_pointers()[entry.column_ids[i]];
|
apply_helper.pointers[i] = entry.table->component_pointers()[entry.column_ids[i]];
|
||||||
|
|
||||||
for (std::size_t i = 0; i < entry.table->row_count(); ++i)
|
for (std::size_t i = 0; i < entry.table->row_count(); ++i)
|
||||||
{
|
{
|
||||||
|
|
@ -290,10 +288,10 @@ namespace psemek::ecs
|
||||||
|
|
||||||
for (auto const & entry : cache->tables)
|
for (auto const & entry : cache->tables)
|
||||||
{
|
{
|
||||||
detail::static_apply_helper<Components...> apply_helper(*this, entry.table->get_entity_handles());
|
detail::static_apply_helper<Components...> apply_helper(*this, entry.table->entity_handles());
|
||||||
|
|
||||||
for (std::size_t i = 0; i < sizeof...(Components); ++i)
|
for (std::size_t i = 0; i < sizeof...(Components); ++i)
|
||||||
apply_helper.pointers[i] = entry.table->get_component_pointers()[entry.column_ids[i]];
|
apply_helper.pointers[i] = entry.table->component_pointers()[entry.column_ids[i]];
|
||||||
|
|
||||||
apply_helper.batch_apply(function);
|
apply_helper.batch_apply(function);
|
||||||
}
|
}
|
||||||
|
|
@ -309,11 +307,11 @@ namespace psemek::ecs
|
||||||
{
|
{
|
||||||
util::uuid const uuid = Component::uuid();
|
util::uuid const uuid = Component::uuid();
|
||||||
|
|
||||||
auto column = table_->get_component_column(uuid);
|
auto column = table_->component_column(uuid);
|
||||||
if (!column)
|
if (!column)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
return reinterpret_cast<Component *>(table_->get_component_pointers()[*column].data + detail::stride<Component>() * row_);
|
return reinterpret_cast<Component *>(table_->component_pointers()[*column].data + detail::stride<Component>() * row_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
|
|
@ -321,7 +319,7 @@ namespace psemek::ecs
|
||||||
{
|
{
|
||||||
if (auto ptr = get_if<Component>())
|
if (auto ptr = get_if<Component>())
|
||||||
return *ptr;
|
return *ptr;
|
||||||
throw component_not_found_exception(typeid(Component), table_->get_entity_handles()[row_]);
|
throw component_not_found_exception(typeid(Component), table_->entity_handles()[row_]);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Component>
|
template <typename Component>
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ namespace psemek::ecs::detail
|
||||||
entry.table = table;
|
entry.table = table;
|
||||||
|
|
||||||
for (auto const & uuid : component_uuids)
|
for (auto const & uuid : component_uuids)
|
||||||
entry.column_ids.push_back(*(table->get_component_column(uuid)));
|
entry.column_ids.push_back(*(table->component_column(uuid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -35,7 +35,7 @@ namespace psemek::ecs
|
||||||
void entity_container::remove_row(detail::table & table, std::uint32_t row, util::span<detail::entity_data> entities)
|
void entity_container::remove_row(detail::table & table, std::uint32_t row, util::span<detail::entity_data> entities)
|
||||||
{
|
{
|
||||||
// Swap with the last row in that table
|
// Swap with the last row in that table
|
||||||
auto table_entity_handles = table.get_entity_handles();
|
auto table_entity_handles = table.entity_handles();
|
||||||
table.swap_rows(row, table_entity_handles.size() - 1);
|
table.swap_rows(row, table_entity_handles.size() - 1);
|
||||||
table.pop_row();
|
table.pop_row();
|
||||||
auto swap_handle = table_entity_handles[row];
|
auto swap_handle = table_entity_handles[row];
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue