+140
@@ -8,6 +8,7 @@
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
namespace libcatboy::ecs::test {
|
||||
|
||||
@@ -939,4 +940,143 @@ TEST_F(RegistryTest, RegistryIsDefaultConstructible) {
|
||||
SUCCEED();
|
||||
}
|
||||
|
||||
// =============================================================================
|
||||
// COMPONENT VIEWS
|
||||
// =============================================================================
|
||||
|
||||
TEST_F(RegistryTest, ViewReturnsEntitiesWithAllRequestedComponents) {
|
||||
const auto e1 = create();
|
||||
const auto e2 = create();
|
||||
const auto e3 = create();
|
||||
|
||||
reg.emplace<position>(e1, 1, 2);
|
||||
reg.emplace<velocity>(e1, 10, 20);
|
||||
|
||||
reg.emplace<position>(e2, 3, 4);
|
||||
|
||||
reg.emplace<position>(e3, 5, 6);
|
||||
reg.emplace<velocity>(e3, 50, 60);
|
||||
|
||||
std::vector<entity> result;
|
||||
|
||||
for (auto [e, p, v] : reg.view<position, velocity>()) {
|
||||
result.push_back(e);
|
||||
|
||||
EXPECT_EQ(p, (position{ e == e1 ? 1 : 5, e == e1 ? 2 : 6 }));
|
||||
EXPECT_EQ(v, (velocity{ e == e1 ? 10 : 50, e == e1 ? 20 : 60 }));
|
||||
}
|
||||
|
||||
ASSERT_EQ(result.size(), 2u);
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e1), result.end());
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e3), result.end());
|
||||
EXPECT_EQ(std::find(result.begin(), result.end(), e2), result.end());
|
||||
}
|
||||
|
||||
TEST_F(RegistryTest, ViewIsEmptyWhenNoEntityHasAllComponents) {
|
||||
const auto e1 = create();
|
||||
const auto e2 = create();
|
||||
|
||||
reg.emplace<position>(e1, 1, 2);
|
||||
reg.emplace<velocity>(e2, 3, 4);
|
||||
|
||||
auto view = reg.view<position, velocity>();
|
||||
|
||||
EXPECT_EQ(view.begin(), view.end());
|
||||
}
|
||||
|
||||
TEST_F(RegistryTest, ViewReturnsMutableComponentReferences) {
|
||||
const auto e = create();
|
||||
|
||||
reg.emplace<position>(e, 1, 2);
|
||||
reg.emplace<velocity>(e, 3, 4);
|
||||
|
||||
for (auto [entity, p, v] : reg.view<position, velocity>()) {
|
||||
EXPECT_EQ(entity, e);
|
||||
|
||||
p.x = 100;
|
||||
v.y = 200;
|
||||
}
|
||||
|
||||
EXPECT_EQ(reg.at<position>(e), (position{ 100, 2 }));
|
||||
EXPECT_EQ(reg.at<velocity>(e), (velocity{ 3, 200 }));
|
||||
}
|
||||
|
||||
TEST_F(RegistryTest, ViewHandlesSparseEntityIDs) {
|
||||
const auto e0 = create();
|
||||
const auto e1 = create();
|
||||
const auto e2 = create();
|
||||
const auto e3 = create();
|
||||
|
||||
reg.emplace<position>(e0, 0, 0);
|
||||
reg.emplace<velocity>(e0, 10, 10);
|
||||
|
||||
reg.emplace<position>(e2, 2, 20);
|
||||
reg.emplace<velocity>(e2, 20, 20);
|
||||
|
||||
reg.emplace<position>(e3, 3, 30);
|
||||
|
||||
std::vector<entity> result;
|
||||
|
||||
for (auto [e, p, v] : reg.view<position, velocity>()) {
|
||||
result.push_back(e);
|
||||
}
|
||||
|
||||
ASSERT_EQ(result.size(), 2u);
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e0), result.end());
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e2), result.end());
|
||||
EXPECT_EQ(std::find(result.begin(), result.end(), e1), result.end());
|
||||
EXPECT_EQ(std::find(result.begin(), result.end(), e3), result.end());
|
||||
}
|
||||
|
||||
TEST_F(RegistryTest, ViewUsesSmallestComponentSetAsDriver) {
|
||||
// Position exists on many entities while velocity exists on only two.
|
||||
// The result should still contain exactly the intersection.
|
||||
//
|
||||
// This primarily exercises the optimization in component_view that picks
|
||||
// the smallest sparse set as the iteration source.
|
||||
for (int i = 0; i < 100; ++i) {
|
||||
const auto e = create();
|
||||
reg.emplace<position>(e, i, i);
|
||||
}
|
||||
|
||||
const auto e1 = create();
|
||||
const auto e2 = create();
|
||||
|
||||
reg.emplace<position>(e1, 100, 100);
|
||||
reg.emplace<velocity>(e1, 1, 1);
|
||||
|
||||
reg.emplace<position>(e2, 200, 200);
|
||||
reg.emplace<velocity>(e2, 2, 2);
|
||||
|
||||
std::vector<entity> result;
|
||||
|
||||
for (auto [e, p, v] : reg.view<position, velocity>())
|
||||
result.push_back(e);
|
||||
|
||||
ASSERT_EQ(result.size(), 2u);
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e1), result.end());
|
||||
EXPECT_NE(std::find(result.begin(), result.end(), e2), result.end());
|
||||
}
|
||||
|
||||
TEST_F(RegistryTest, ViewStopsReturningEntityAfterComponentIsErased) {
|
||||
const auto e1 = create();
|
||||
const auto e2 = create();
|
||||
|
||||
reg.emplace<position>(e1, 1, 2);
|
||||
reg.emplace<velocity>(e1, 3, 4);
|
||||
|
||||
reg.emplace<position>(e2, 5, 6);
|
||||
reg.emplace<velocity>(e2, 7, 8);
|
||||
|
||||
reg.erase<velocity>(e1);
|
||||
|
||||
std::vector<entity> result;
|
||||
|
||||
for (auto [e, p, v] : reg.view<position, velocity>())
|
||||
result.push_back(e);
|
||||
|
||||
ASSERT_EQ(result.size(), 1u);
|
||||
EXPECT_EQ(result.front(), e2);
|
||||
}
|
||||
|
||||
} // namespace libcatboy::ecs::test
|
||||
|
||||
Reference in New Issue
Block a user