view: allow swapping storage elements of a view
This commit is contained in:
1
TODO
1
TODO
@@ -7,6 +7,7 @@ DOC:
|
||||
* examples (and credits) from @alanjfs :)
|
||||
* update entity doc when the storage based model is in place
|
||||
* in-place O(1) release/destroy for non-orphaned entities, out-of-sync model
|
||||
* storage swap on views and empty views (once the static storage in the registry is removed)
|
||||
|
||||
TODO (high prio):
|
||||
* check natvis files (periodically :)
|
||||
|
||||
@@ -199,6 +199,7 @@ class basic_view;
|
||||
*/
|
||||
template<typename... Get, typename... Exclude>
|
||||
class basic_view<get_t<Get...>, exclude_t<Exclude...>> {
|
||||
static constexpr auto offset = sizeof...(Get);
|
||||
using base_type = std::common_type_t<typename Get::base_type..., typename Exclude::base_type...>;
|
||||
using underlying_type = typename base_type::entity_type;
|
||||
|
||||
@@ -267,7 +268,7 @@ public:
|
||||
basic_view(Get &...value, Exclude &...excl) noexcept
|
||||
: pools{&value...},
|
||||
filter{&excl...},
|
||||
view{std::get<0>(pools)} {
|
||||
view{} {
|
||||
refresh();
|
||||
}
|
||||
|
||||
@@ -299,7 +300,8 @@ public:
|
||||
|
||||
/*! @brief Updates the internal leading view if required. */
|
||||
void refresh() noexcept {
|
||||
std::apply([this](auto *...elem) { ((this->view = elem->size() < this->view->size() ? elem : this->view), ...); }, pools);
|
||||
view = std::get<0>(pools);
|
||||
std::apply([this](auto *, auto *...other) { ((this->view = other->size() < this->view->size() ? other : this->view), ...); }, pools);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,8 +329,6 @@ public:
|
||||
*/
|
||||
template<std::size_t Index>
|
||||
[[nodiscard]] auto *storage() const noexcept {
|
||||
constexpr auto offset = sizeof...(Get);
|
||||
|
||||
if constexpr(Index < offset) {
|
||||
return std::get<Index>(pools);
|
||||
} else {
|
||||
@@ -336,6 +336,36 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a storage to a view.
|
||||
* @tparam Type Type of storage to assign to the view.
|
||||
* @param elem A storage to assign to the view.
|
||||
*/
|
||||
template<typename Type>
|
||||
void storage(Type &elem) noexcept {
|
||||
storage<index_of<typename Type::value_type>>(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a storage to a view.
|
||||
* @tparam Index Index of the storage to assign to the view.
|
||||
* @tparam Type Type of storage to assign to the view.
|
||||
* @param elem A storage to assign to the view.
|
||||
*/
|
||||
template<std::size_t Index, typename Type>
|
||||
void storage(Type &elem) noexcept {
|
||||
if constexpr(Index < offset) {
|
||||
view = (std::get<Index>(pools) == view ? nullptr : view);
|
||||
std::get<Index>(pools) = &elem;
|
||||
} else {
|
||||
std::get<Index - offset>(filter) = &elem;
|
||||
}
|
||||
|
||||
if(view == nullptr && std::apply([](const auto *...curr) { return ((curr != nullptr) && ...); }, pools)) {
|
||||
refresh();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Estimates the number of entities iterated by the view.
|
||||
* @return Estimated number of entities iterated by the view.
|
||||
@@ -610,6 +640,24 @@ public:
|
||||
return std::get<Index>(pools);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a storage to a view.
|
||||
* @param elem A storage to assign to the view.
|
||||
*/
|
||||
void storage(Get &elem) noexcept {
|
||||
storage<0>(elem);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Assigns a storage to a view.
|
||||
* @tparam Index Index of the storage to assign to the view.
|
||||
* @param elem A storage to assign to the view.
|
||||
*/
|
||||
template<std::size_t Index>
|
||||
void storage(Get &elem) noexcept {
|
||||
view = std::get<Index>(pools) = &elem;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the number of entities that have the given component.
|
||||
* @return Number of entities that have the given component.
|
||||
|
||||
@@ -509,6 +509,41 @@ TEST(SingleComponentView, Storage) {
|
||||
ASSERT_EQ(cview.storage<const char>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(SingleComponentView, SwapStorage) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<>> view;
|
||||
entt::basic_view<entt::get_t<const entt::storage<int>>, entt::exclude_t<>> cview;
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
ASSERT_FALSE(cview);
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(cview.storage<const int>(), nullptr);
|
||||
|
||||
const entt::entity entity{42u};
|
||||
registry.emplace<int>(entity);
|
||||
|
||||
view.storage(registry.storage<int>());
|
||||
cview.storage(registry.storage<int>());
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_TRUE(cview);
|
||||
ASSERT_NE(view.storage<0u>(), nullptr);
|
||||
ASSERT_NE(cview.storage<const int>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size(), 1u);
|
||||
ASSERT_EQ(cview.size(), 1u);
|
||||
ASSERT_TRUE(view.contains(entity));
|
||||
ASSERT_TRUE(cview.contains(entity));
|
||||
|
||||
view.storage(registry.storage<int>("other"_hs));
|
||||
cview.storage(registry.storage<int>("other"_hs));
|
||||
|
||||
ASSERT_TRUE(view.empty());
|
||||
ASSERT_TRUE(cview.empty());
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, Functionalities) {
|
||||
entt::registry registry;
|
||||
auto view = registry.view<int, char>();
|
||||
@@ -1338,6 +1373,40 @@ TEST(MultiComponentView, Storage) {
|
||||
ASSERT_EQ(view.storage<const float>(), nullptr);
|
||||
}
|
||||
|
||||
TEST(MultiComponentView, SwapStorage) {
|
||||
using namespace entt::literals;
|
||||
|
||||
entt::registry registry;
|
||||
entt::basic_view<entt::get_t<entt::storage<int>>, entt::exclude_t<const entt::storage<char>>> view;
|
||||
|
||||
ASSERT_FALSE(view);
|
||||
ASSERT_EQ(view.storage<0u>(), nullptr);
|
||||
ASSERT_EQ(view.storage<const char>(), nullptr);
|
||||
|
||||
const entt::entity entity{42u};
|
||||
registry.emplace<int>(entity);
|
||||
registry.emplace<char>(entity);
|
||||
|
||||
view.storage(registry.storage<int>());
|
||||
view.storage<1u>(registry.storage<char>());
|
||||
|
||||
ASSERT_TRUE(view);
|
||||
ASSERT_NE(view.storage<int>(), nullptr);
|
||||
ASSERT_NE(view.storage<1u>(), nullptr);
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_FALSE(view.contains(entity));
|
||||
|
||||
view.storage(registry.storage<char>("other"_hs));
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 1u);
|
||||
ASSERT_TRUE(view.contains(entity));
|
||||
|
||||
view.storage(registry.storage<int>("empty"_hs));
|
||||
|
||||
ASSERT_EQ(view.size_hint(), 0u);
|
||||
}
|
||||
|
||||
TEST(View, Pipe) {
|
||||
entt::registry registry;
|
||||
const auto entity = registry.create();
|
||||
|
||||
Reference in New Issue
Block a user