variadic get_components and find_components

This commit is contained in:
2018-12-26 04:51:45 +07:00
parent 32fb2f2790
commit 3c2d057ece
2 changed files with 144 additions and 4 deletions

69
ecs.hpp
View File

@@ -10,6 +10,7 @@
#include <cstddef>
#include <cstdint>
#include <tuple>
#include <mutex>
#include <memory>
#include <limits>
@@ -226,6 +227,16 @@ namespace ecs_hpp
template < typename T >
const T* find_component() const noexcept;
template < typename... Ts >
std::tuple<Ts&...> get_components();
template < typename... Ts >
std::tuple<const Ts&...> get_components() const;
template < typename... Ts >
std::tuple<Ts*...> find_components() noexcept;
template < typename... Ts >
std::tuple<const Ts*...> find_components() const noexcept;
private:
world& owner_;
entity_id id_{0u};
@@ -285,6 +296,16 @@ namespace ecs_hpp
template < typename T >
const T* find_component(const entity& ent) const noexcept;
template < typename... Ts >
std::tuple<Ts&...> get_components(const entity& ent);
template < typename... Ts >
std::tuple<const Ts&...> get_components(const entity& ent) const;
template < typename... Ts >
std::tuple<Ts*...> find_components(const entity& ent) noexcept;
template < typename... Ts >
std::tuple<const Ts*...> find_components(const entity& ent) const noexcept;
template < typename T, typename F >
void for_each_component(F&& f);
template < typename T, typename F >
@@ -363,7 +384,7 @@ namespace ecs_hpp
}
inline bool entity::is_alive() const noexcept {
return owner_.is_entity_alive(*this);
return const_cast<const world&>(owner_).is_entity_alive(*this);
}
template < typename T, typename... Args >
@@ -380,7 +401,7 @@ namespace ecs_hpp
template < typename T >
bool entity::exists_component() const noexcept {
return owner_.exists_component<T>(*this);
return const_cast<const world&>(owner_).exists_component<T>(*this);
}
inline std::size_t entity::remove_all_components() noexcept {
@@ -394,7 +415,7 @@ namespace ecs_hpp
template < typename T >
const T& entity::get_component() const {
return owner_.get_component<T>(*this);
return const_cast<const world&>(owner_).get_component<T>(*this);
}
template < typename T >
@@ -404,7 +425,27 @@ namespace ecs_hpp
template < typename T >
const T* entity::find_component() const noexcept {
return owner_.find_component<T>(*this);
return const_cast<const world&>(owner_).find_component<T>(*this);
}
template < typename... Ts >
std::tuple<Ts&...> entity::get_components() {
return owner_.get_components<Ts...>(*this);
}
template < typename... Ts >
std::tuple<const Ts&...> entity::get_components() const {
return const_cast<const world&>(owner_).get_components<Ts...>(*this);
}
template < typename... Ts >
std::tuple<Ts*...> entity::find_components() noexcept {
return owner_.find_components<Ts...>(*this);
}
template < typename... Ts >
std::tuple<const Ts*...> entity::find_components() const noexcept {
return const_cast<const world&>(owner_).find_components<Ts...>(*this);
}
inline bool operator==(const entity& l, const entity& r) noexcept {
@@ -520,6 +561,26 @@ namespace ecs_hpp
return find_component_impl_<T>(ent);
}
template < typename... Ts >
std::tuple<Ts&...> world::get_components(const entity& ent) {
return std::make_tuple(std::ref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<const Ts&...> world::get_components(const entity& ent) const {
return std::make_tuple(std::cref(get_component<Ts>(ent))...);
}
template < typename... Ts >
std::tuple<Ts*...> world::find_components(const entity& ent) noexcept {
return std::make_tuple(find_component<Ts>(ent)...);
}
template < typename... Ts >
std::tuple<const Ts*...> world::find_components(const entity& ent) const noexcept {
return std::make_tuple(find_component<Ts>(ent)...);
}
template < typename T, typename F >
void world::for_each_component(F&& f) {
std::lock_guard<std::mutex> guard(mutex_);

View File

@@ -27,6 +27,16 @@ namespace
velocity_c() = default;
velocity_c(int nx, int ny) : x(nx), y(ny) {}
};
bool operator==(const position_c& l, const position_c& r) noexcept {
return l.x == r.x
&& l.y == r.y;
}
bool operator==(const velocity_c& l, const velocity_c& r) noexcept {
return l.x == r.x
&& l.y == r.y;
}
}
TEST_CASE("detail") {
@@ -202,6 +212,75 @@ TEST_CASE("world") {
REQUIRE_FALSE(ww.find_component<velocity_c>(e2));
}
}
{
ecs::world w;
auto e1 = w.create_entity();
REQUIRE(e1.find_components<>() ==
std::make_tuple());
REQUIRE(e1.find_components<velocity_c>() ==
std::make_tuple<velocity_c*>(nullptr));
REQUIRE(e1.find_components<position_c, velocity_c>() ==
std::make_tuple<position_c*, velocity_c*>(nullptr, nullptr));
REQUIRE(e1.get_components<>() == std::make_tuple());
REQUIRE_THROWS(e1.get_components<velocity_c>());
REQUIRE_THROWS(e1.get_components<position_c, velocity_c>());
{
const auto ee1 = e1;
REQUIRE(ee1.find_components<>() ==
std::make_tuple());
REQUIRE(ee1.find_components<velocity_c>() ==
std::make_tuple<velocity_c*>(nullptr));
REQUIRE(ee1.find_components<position_c, velocity_c>() ==
std::make_tuple<position_c*, velocity_c*>(nullptr, nullptr));
REQUIRE(ee1.get_components<>() == std::make_tuple());
REQUIRE_THROWS(ee1.get_components<velocity_c>());
REQUIRE_THROWS(ee1.get_components<position_c, velocity_c>());
}
e1.assign_component<velocity_c>(3, 4);
REQUIRE(e1.find_components<velocity_c>() ==
std::make_tuple<velocity_c*>(e1.find_component<velocity_c>()));
REQUIRE(e1.find_components<position_c, velocity_c>() ==
std::make_tuple<position_c*, velocity_c*>(nullptr, e1.find_component<velocity_c>()));
REQUIRE(e1.get_components<velocity_c>() ==
std::make_tuple<velocity_c&>(e1.get_component<velocity_c>()));
REQUIRE_THROWS(e1.get_components<position_c, velocity_c>());
{
const auto ee1 = e1;
REQUIRE(ee1.find_components<velocity_c>() ==
std::make_tuple<velocity_c*>(e1.find_component<velocity_c>()));
REQUIRE(ee1.find_components<position_c, velocity_c>() ==
std::make_tuple<position_c*, velocity_c*>(nullptr, e1.find_component<velocity_c>()));
REQUIRE(ee1.get_components<velocity_c>() ==
std::make_tuple<const velocity_c&>(ee1.get_component<velocity_c>()));
REQUIRE_THROWS(ee1.get_components<position_c, velocity_c>());
}
e1.assign_component<position_c>(1, 2);
auto p = e1.get_components<position_c, velocity_c>();
std::get<0>(p).x = 10;
std::get<1>(p).x = 30;
REQUIRE(e1.get_component<position_c>().x == 10);
REQUIRE(e1.get_component<velocity_c>().x == 30);
auto p2 = e1.find_components<position_c, velocity_c>();
std::get<0>(p2)->y = 20;
std::get<1>(p2)->y = 40;
REQUIRE(e1.get_component<position_c>().y == 20);
REQUIRE(e1.get_component<velocity_c>().y == 40);
}
}
SECTION("for_each_component") {
{