mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-13 02:26:27 +07:00
add minimal aspects
This commit is contained in:
@@ -55,6 +55,10 @@ namespace ecs_hpp
|
||||
class option_conj;
|
||||
template < typename... Ts >
|
||||
class option_disj;
|
||||
class option_bool;
|
||||
|
||||
template < typename... Ts >
|
||||
class aspect;
|
||||
|
||||
class entity_filler;
|
||||
class registry_filler;
|
||||
@@ -1390,6 +1394,18 @@ namespace ecs_hpp
|
||||
template < typename T >
|
||||
detail::component_storage<T>& get_or_create_storage_();
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
void for_joined_components_impl_(
|
||||
std::index_sequence<>,
|
||||
F&& f,
|
||||
Opts&&... opts);
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
void for_joined_components_impl_(
|
||||
std::index_sequence<>,
|
||||
F&& f,
|
||||
Opts&&... opts) const;
|
||||
|
||||
template < typename T
|
||||
, typename... Ts
|
||||
, typename F
|
||||
@@ -1508,6 +1524,11 @@ namespace ecs_hpp
|
||||
static constexpr bool instance = true;
|
||||
};
|
||||
|
||||
template <>
|
||||
struct option<option_bool> {
|
||||
static constexpr bool instance = true;
|
||||
};
|
||||
|
||||
//
|
||||
// options
|
||||
//
|
||||
@@ -1583,6 +1604,19 @@ namespace ecs_hpp
|
||||
std::tuple<Ts...> opts_;
|
||||
};
|
||||
|
||||
class option_bool final {
|
||||
public:
|
||||
option_bool(bool b)
|
||||
: bool_(b) {}
|
||||
|
||||
bool operator()(const const_entity& e) const {
|
||||
(void)e;
|
||||
return bool_;
|
||||
}
|
||||
private:
|
||||
bool bool_{false};
|
||||
};
|
||||
|
||||
//
|
||||
// operators
|
||||
//
|
||||
@@ -1608,6 +1642,57 @@ namespace ecs_hpp
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// aspect
|
||||
//
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
namespace ecs_hpp
|
||||
{
|
||||
template < typename... Ts >
|
||||
class aspect {
|
||||
public:
|
||||
static auto to_option() noexcept {
|
||||
return (option_bool{true} && ... && exists<Ts>{});
|
||||
}
|
||||
|
||||
static bool match_entity(const const_entity& e) noexcept {
|
||||
return (... && e.exists_component<Ts>());
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
static void for_each_entity(registry& owner, F&& f, Opts&&... opts) {
|
||||
owner.for_joined_components<Ts...>(
|
||||
[&f](const auto& e, const auto&...){
|
||||
f(e);
|
||||
}, std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
static void for_each_entity(const registry& owner, F&& f, Opts&&... opts) {
|
||||
owner.for_joined_components<Ts...>(
|
||||
[&f](const auto& e, const auto&...){
|
||||
f(e);
|
||||
}, std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
static void for_joined_components(registry& owner, F&& f, Opts&&... opts) {
|
||||
owner.for_joined_components<Ts...>(
|
||||
std::forward<F>(f),
|
||||
std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
static void for_joined_components(const registry& owner, F&& f, Opts&&... opts) {
|
||||
owner.for_joined_components<Ts...>(
|
||||
std::forward<F>(f),
|
||||
std::forward<Opts>(opts)...);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
//
|
||||
// fillers
|
||||
@@ -2683,6 +2768,24 @@ namespace ecs_hpp
|
||||
storages_.get(family).get());
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
void registry::for_joined_components_impl_(
|
||||
std::index_sequence<>,
|
||||
F&& f,
|
||||
Opts&&... opts)
|
||||
{
|
||||
for_each_entity(std::forward<F>(f), std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template < typename F, typename... Opts >
|
||||
void registry::for_joined_components_impl_(
|
||||
std::index_sequence<>,
|
||||
F&& f,
|
||||
Opts&&... opts) const
|
||||
{
|
||||
for_each_entity(std::forward<F>(f), std::forward<Opts>(opts)...);
|
||||
}
|
||||
|
||||
template < typename T
|
||||
, typename... Ts
|
||||
, typename F
|
||||
|
||||
@@ -1185,6 +1185,102 @@ TEST_CASE("registry") {
|
||||
});
|
||||
}
|
||||
}
|
||||
SECTION("aspects") {
|
||||
{
|
||||
using empty_aspect = ecs::aspect<>;
|
||||
|
||||
ecs::registry w;
|
||||
|
||||
ecs::entity e1 = w.create_entity();
|
||||
REQUIRE(empty_aspect::match_entity(e1));
|
||||
|
||||
ecs::entity e2 = w.create_entity();
|
||||
e2.assign_component<movable_c>();
|
||||
e2.assign_component<position_c>(1,2);
|
||||
REQUIRE(empty_aspect::match_entity(e2));
|
||||
|
||||
ecs::entity e3 = w.create_entity();
|
||||
e3.assign_component<movable_c>();
|
||||
e3.assign_component<position_c>(1,2);
|
||||
e3.assign_component<velocity_c>(3,4);
|
||||
REQUIRE(empty_aspect::match_entity(e3));
|
||||
|
||||
{
|
||||
ecs::entity_id acc{};
|
||||
empty_aspect::for_each_entity(w, [&acc](ecs::entity e){
|
||||
acc += e.id();
|
||||
}, ecs::exists<movable_c>{});
|
||||
REQUIRE(acc == e2.id() + e3.id());
|
||||
}
|
||||
|
||||
{
|
||||
ecs::entity_id acc{};
|
||||
empty_aspect::for_joined_components(w, [&acc](ecs::entity e){
|
||||
acc += e.id();
|
||||
}, ecs::exists<movable_c>{});
|
||||
REQUIRE(acc == e2.id() + e3.id());
|
||||
}
|
||||
|
||||
{
|
||||
ecs::entity_id acc{};
|
||||
w.for_each_entity([&acc](ecs::entity e){
|
||||
acc += e.id();
|
||||
}, empty_aspect::to_option());
|
||||
REQUIRE(acc == e1.id() + e2.id() + e3.id());
|
||||
}
|
||||
}
|
||||
{
|
||||
using movable = ecs::aspect<
|
||||
position_c,
|
||||
velocity_c>;
|
||||
|
||||
ecs::registry w;
|
||||
|
||||
ecs::entity e = w.create_entity();
|
||||
REQUIRE_FALSE(movable::match_entity(e));
|
||||
|
||||
e.assign_component<position_c>(1,2);
|
||||
REQUIRE_FALSE(movable::match_entity(e));
|
||||
|
||||
e.assign_component<velocity_c>(3,4);
|
||||
REQUIRE(movable::match_entity(e));
|
||||
|
||||
ecs::entity e2 = w.create_entity();
|
||||
e2.assign_component<position_c>(1,2);
|
||||
|
||||
movable::for_joined_components(w,
|
||||
[](ecs::entity_id, position_c& p, const velocity_c& v){
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
});
|
||||
|
||||
movable::for_joined_components(std::as_const(w),
|
||||
[](ecs::entity_id, const position_c& p, const velocity_c& v){
|
||||
const_cast<position_c&>(p).x += v.x;
|
||||
const_cast<position_c&>(p).y += v.y;
|
||||
});
|
||||
|
||||
w.for_each_entity([](ecs::entity e){
|
||||
auto& p = e.get_component<position_c>();
|
||||
const auto& v = e.get_component<velocity_c>();
|
||||
p.x += v.x;
|
||||
p.y += v.y;
|
||||
}, movable::to_option());
|
||||
|
||||
std::as_const(w).for_each_entity([](const ecs::const_entity& e){
|
||||
const auto& p = e.get_component<position_c>();
|
||||
const auto& v = e.get_component<velocity_c>();
|
||||
const_cast<position_c&>(p).x += v.x;
|
||||
const_cast<position_c&>(p).y += v.y;
|
||||
}, movable::to_option());
|
||||
|
||||
REQUIRE(e.get_component<position_c>().x == 1 + 3*4);
|
||||
REQUIRE(e.get_component<position_c>().y == 2 + 4*4);
|
||||
|
||||
REQUIRE(e2.get_component<position_c>().x == 1);
|
||||
REQUIRE(e2.get_component<position_c>().y == 2);
|
||||
}
|
||||
}
|
||||
SECTION("options") {
|
||||
{
|
||||
ecs::registry w;
|
||||
|
||||
Reference in New Issue
Block a user