mirror of
https://github.com/BlackMATov/ecs.hpp.git
synced 2025-12-15 11:53:51 +07:00
@@ -1099,23 +1099,30 @@ namespace ecs_hpp
|
|||||||
{
|
{
|
||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
class component_applier_base;
|
class applier_base;
|
||||||
using component_applier_uptr = std::unique_ptr<component_applier_base>;
|
using applier_uptr = std::unique_ptr<applier_base>;
|
||||||
|
|
||||||
class component_applier_base {
|
class applier_base {
|
||||||
public:
|
public:
|
||||||
virtual ~component_applier_base() = default;
|
virtual ~applier_base() = default;
|
||||||
virtual component_applier_uptr clone() const = 0;
|
virtual applier_uptr clone() const = 0;
|
||||||
virtual void apply_to(entity& ent, bool override) const = 0;
|
virtual void apply_to_entity(entity& ent, bool override) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
class typed_applier : public applier_base {
|
||||||
|
public:
|
||||||
|
virtual void apply_to_component(T& component) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
class component_applier final : public component_applier_base {
|
class typed_applier_with_args final : public typed_applier<T> {
|
||||||
public:
|
public:
|
||||||
component_applier(std::tuple<Args...>&& args);
|
typed_applier_with_args(std::tuple<Args...>&& args);
|
||||||
component_applier(const std::tuple<Args...>& args);
|
typed_applier_with_args(const std::tuple<Args...>& args);
|
||||||
component_applier_uptr clone() const override;
|
applier_uptr clone() const override;
|
||||||
void apply_to(entity& ent, bool override) const override;
|
void apply_to_entity(entity& ent, bool override) const override;
|
||||||
|
void apply_to_component(T& component) const override;
|
||||||
private:
|
private:
|
||||||
std::tuple<Args...> args_;
|
std::tuple<Args...> args_;
|
||||||
};
|
};
|
||||||
@@ -1147,11 +1154,13 @@ namespace ecs_hpp
|
|||||||
prototype& merge_with(const prototype& other, bool override) &;
|
prototype& merge_with(const prototype& other, bool override) &;
|
||||||
prototype&& merge_with(const prototype& other, bool override) &&;
|
prototype&& merge_with(const prototype& other, bool override) &&;
|
||||||
|
|
||||||
void apply_to(entity& ent, bool override) const;
|
template < typename T >
|
||||||
|
bool apply_to_component(T& component) const;
|
||||||
|
void apply_to_entity(entity& ent, bool override) const;
|
||||||
private:
|
private:
|
||||||
detail::sparse_map<
|
detail::sparse_map<
|
||||||
family_id,
|
family_id,
|
||||||
detail::component_applier_uptr> appliers_;
|
detail::applier_uptr> appliers_;
|
||||||
};
|
};
|
||||||
|
|
||||||
void swap(prototype& l, prototype& r) noexcept;
|
void swap(prototype& l, prototype& r) noexcept;
|
||||||
@@ -1840,31 +1849,38 @@ namespace ecs_hpp
|
|||||||
namespace detail
|
namespace detail
|
||||||
{
|
{
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
component_applier<T,Args...>::component_applier(std::tuple<Args...>&& args)
|
typed_applier_with_args<T, Args...>::typed_applier_with_args(std::tuple<Args...>&& args)
|
||||||
: args_(std::move(args)) {}
|
: args_(std::move(args)) {}
|
||||||
|
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
component_applier<T,Args...>::component_applier(const std::tuple<Args...>& args)
|
typed_applier_with_args<T, Args...>::typed_applier_with_args(const std::tuple<Args...>& args)
|
||||||
: args_(args) {}
|
: args_(args) {}
|
||||||
|
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
component_applier_uptr component_applier<T,Args...>::clone() const {
|
applier_uptr typed_applier_with_args<T, Args...>::clone() const {
|
||||||
return std::make_unique<component_applier>(args_);
|
return std::make_unique<typed_applier_with_args>(args_);
|
||||||
}
|
}
|
||||||
|
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
void component_applier<T,Args...>::apply_to(entity& ent, bool override) const {
|
void typed_applier_with_args<T, Args...>::apply_to_entity(entity& ent, bool override) const {
|
||||||
detail::tiny_tuple_apply([&ent, override](const Args&... args){
|
detail::tiny_tuple_apply([&ent, override](const Args&... args){
|
||||||
if ( override || !ent.exists_component<T>() ) {
|
if ( override || !ent.exists_component<T>() ) {
|
||||||
ent.assign_component<T>(args...);
|
ent.assign_component<T>(args...);
|
||||||
}
|
}
|
||||||
}, args_);
|
}, args_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template < typename T, typename... Args >
|
||||||
|
void typed_applier_with_args<T, Args...>::apply_to_component(T& component) const {
|
||||||
|
detail::tiny_tuple_apply([&component](const Args&... args){
|
||||||
|
component = T(args...);
|
||||||
|
}, args_);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inline prototype::prototype(const prototype& other) {
|
inline prototype::prototype(const prototype& other) {
|
||||||
for ( const family_id id : other.appliers_ ) {
|
for ( const family_id family : other.appliers_ ) {
|
||||||
appliers_.insert(id, other.appliers_.get(id)->clone());
|
appliers_.insert(family, other.appliers_.get(family)->clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1908,7 +1924,7 @@ namespace ecs_hpp
|
|||||||
|
|
||||||
template < typename T, typename... Args >
|
template < typename T, typename... Args >
|
||||||
prototype& prototype::component(Args&&... args) & {
|
prototype& prototype::component(Args&&... args) & {
|
||||||
using applier_t = detail::component_applier<
|
using applier_t = detail::typed_applier_with_args<
|
||||||
T,
|
T,
|
||||||
std::decay_t<Args>...>;
|
std::decay_t<Args>...>;
|
||||||
auto applier = std::make_unique<applier_t>(
|
auto applier = std::make_unique<applier_t>(
|
||||||
@@ -1925,11 +1941,11 @@ namespace ecs_hpp
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline prototype& prototype::merge_with(const prototype& other, bool override) & {
|
inline prototype& prototype::merge_with(const prototype& other, bool override) & {
|
||||||
for ( const auto family_id : other.appliers_ ) {
|
for ( const auto family : other.appliers_ ) {
|
||||||
if ( override || !appliers_.has(family_id) ) {
|
if ( override || !appliers_.has(family) ) {
|
||||||
appliers_.insert_or_assign(
|
appliers_.insert_or_assign(
|
||||||
family_id,
|
family,
|
||||||
other.appliers_.get(family_id)->clone());
|
other.appliers_.get(family)->clone());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return *this;
|
return *this;
|
||||||
@@ -1940,9 +1956,22 @@ namespace ecs_hpp
|
|||||||
return std::move(*this);
|
return std::move(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void prototype::apply_to(entity& ent, bool override) const {
|
template < typename T >
|
||||||
for ( const auto family_id : appliers_ ) {
|
bool prototype::apply_to_component(T& component) const {
|
||||||
appliers_.get(family_id)->apply_to(ent, override);
|
const auto family = detail::type_family<T>::id();
|
||||||
|
const auto applier_base_ptr = appliers_.find(family);
|
||||||
|
if ( !applier_base_ptr ) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
using applier_t = detail::typed_applier<T>;
|
||||||
|
const auto applier = static_cast<applier_t*>(applier_base_ptr->get());
|
||||||
|
applier->apply_to_component(component);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void prototype::apply_to_entity(entity& ent, bool override) const {
|
||||||
|
for ( const auto family : appliers_ ) {
|
||||||
|
appliers_.get(family)->apply_to_entity(ent, override);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2096,7 +2125,7 @@ namespace ecs_hpp
|
|||||||
inline entity registry::create_entity(const prototype& proto) {
|
inline entity registry::create_entity(const prototype& proto) {
|
||||||
auto ent = create_entity();
|
auto ent = create_entity();
|
||||||
try {
|
try {
|
||||||
proto.apply_to(ent, true);
|
proto.apply_to_entity(ent, true);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
destroy_entity(ent);
|
destroy_entity(ent);
|
||||||
throw;
|
throw;
|
||||||
@@ -2108,8 +2137,8 @@ namespace ecs_hpp
|
|||||||
assert(valid_entity(proto));
|
assert(valid_entity(proto));
|
||||||
entity ent = create_entity();
|
entity ent = create_entity();
|
||||||
try {
|
try {
|
||||||
for ( const auto family_id : storages_ ) {
|
for ( const auto family : storages_ ) {
|
||||||
storages_.get(family_id)->clone(proto, ent.id());
|
storages_.get(family)->clone(proto, ent.id());
|
||||||
}
|
}
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
destroy_entity(ent);
|
destroy_entity(ent);
|
||||||
@@ -2161,8 +2190,8 @@ namespace ecs_hpp
|
|||||||
inline std::size_t registry::remove_all_components(const uentity& ent) noexcept {
|
inline std::size_t registry::remove_all_components(const uentity& ent) noexcept {
|
||||||
assert(valid_entity(ent));
|
assert(valid_entity(ent));
|
||||||
std::size_t removed_count = 0u;
|
std::size_t removed_count = 0u;
|
||||||
for ( const auto family_id : storages_ ) {
|
for ( const auto family : storages_ ) {
|
||||||
if ( storages_.get(family_id)->remove(ent) ) {
|
if ( storages_.get(family)->remove(ent) ) {
|
||||||
++removed_count;
|
++removed_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2246,8 +2275,8 @@ namespace ecs_hpp
|
|||||||
inline std::size_t registry::entity_component_count(const const_uentity& ent) const noexcept {
|
inline std::size_t registry::entity_component_count(const const_uentity& ent) const noexcept {
|
||||||
assert(valid_entity(ent));
|
assert(valid_entity(ent));
|
||||||
std::size_t component_count = 0u;
|
std::size_t component_count = 0u;
|
||||||
for ( const auto family_id : storages_ ) {
|
for ( const auto family : storages_ ) {
|
||||||
if ( storages_.get(family_id)->has(ent) ) {
|
if ( storages_.get(family)->has(ent) ) {
|
||||||
++component_count;
|
++component_count;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2348,8 +2377,8 @@ namespace ecs_hpp
|
|||||||
memory_usage_info info;
|
memory_usage_info info;
|
||||||
info.entities += free_entity_ids_.capacity() * sizeof(free_entity_ids_[0]);
|
info.entities += free_entity_ids_.capacity() * sizeof(free_entity_ids_[0]);
|
||||||
info.entities += entity_ids_.memory_usage();
|
info.entities += entity_ids_.memory_usage();
|
||||||
for ( const auto family_id : storages_ ) {
|
for ( const auto family : storages_ ) {
|
||||||
info.components += storages_.get(family_id)->memory_usage();
|
info.components += storages_.get(family)->memory_usage();
|
||||||
}
|
}
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -661,6 +661,37 @@ TEST_CASE("registry") {
|
|||||||
REQUIRE(e4.get_component<position_c>() == position_c(1,2));
|
REQUIRE(e4.get_component<position_c>() == position_c(1,2));
|
||||||
REQUIRE(e4.get_component<velocity_c>() == velocity_c(3,4));
|
REQUIRE(e4.get_component<velocity_c>() == velocity_c(3,4));
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
const auto p1 = ecs::prototype()
|
||||||
|
.component<position_c>(1,2)
|
||||||
|
.component<velocity_c>(3,4);
|
||||||
|
|
||||||
|
position_c c1;
|
||||||
|
velocity_c c2;
|
||||||
|
movable_c c3;
|
||||||
|
|
||||||
|
REQUIRE(p1.apply_to_component(c1));
|
||||||
|
REQUIRE(p1.apply_to_component(c2));
|
||||||
|
REQUIRE_FALSE(p1.apply_to_component(c3));
|
||||||
|
|
||||||
|
REQUIRE(c1 == position_c(1,2));
|
||||||
|
REQUIRE(c2 == velocity_c(3,4));
|
||||||
|
}
|
||||||
|
{
|
||||||
|
const auto p1 = ecs::prototype()
|
||||||
|
.component<position_c>(1,2);
|
||||||
|
|
||||||
|
position_c c1;
|
||||||
|
velocity_c c2;
|
||||||
|
movable_c c3;
|
||||||
|
|
||||||
|
REQUIRE(p1.apply_to_component(c1));
|
||||||
|
REQUIRE_FALSE(p1.apply_to_component(c2));
|
||||||
|
REQUIRE_FALSE(p1.apply_to_component(c3));
|
||||||
|
|
||||||
|
REQUIRE(c1 == position_c(1,2));
|
||||||
|
REQUIRE(c2 == velocity_c(0,0));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
SECTION("component_assigning") {
|
SECTION("component_assigning") {
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user