mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-16 14:11:14 +07:00
variadic get_components and find_components
This commit is contained in:
69
ecs.hpp
69
ecs.hpp
@@ -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_);
|
||||
|
||||
@@ -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") {
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user