diff --git a/libs/ecs/include/psemek/ecs/entity_accessor.hpp b/libs/ecs/include/psemek/ecs/entity_accessor.hpp new file mode 100644 index 00000000..d08499dc --- /dev/null +++ b/libs/ecs/include/psemek/ecs/entity_accessor.hpp @@ -0,0 +1,112 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +#include + +namespace psemek::ecs +{ + + struct component_not_found_exception + : util::exception + { + component_not_found_exception(std::type_info const & type, entity_handle const & handle, boost::stacktrace::stacktrace stacktrace = {}) + : util::exception(util::to_string("Component ", util::type_name(type), " not found for entity ", handle), std::move(stacktrace)) + , type_(type) + , handle_(handle) + {} + + std::type_info const & type() const + { + return type_; + } + + entity_handle const & handle() const + { + return handle_; + } + + private: + std::type_info const & type_; + entity_handle handle_; + }; + + struct entity_accessor + { + entity_accessor() = default; + entity_accessor(entity_accessor const &) = default; + + explicit operator bool() const; + + /** Obtain a pointer to the specified component type + * of the accessed entity, or a null pointer if + * the entity doesn't contain this component type. + */ + template + Component * get_if(); + + /** Obtain a reference to the specified component type + * of the accessed entity. + * If the entity doesn't contain this component type, + * an exception of type `component_not_found_exception` is thrown. + */ + template + Component & get(); + + /** Check if the entity contains this component type. + */ + template + bool contains() const; + + private: + detail::table * table_ = nullptr; + std::uint32_t row_ = 0; + + friend struct entity_container; + + entity_accessor(detail::table * table, std::uint32_t row); + }; + + inline entity_accessor::operator bool() const + { + return table_ != nullptr; + } + + template + Component * entity_accessor::get_if() + { + util::uuid const uuid = Component::uuid(); + + auto column = table_->column(uuid); + if (!column) + return nullptr; + + return reinterpret_cast(column->data() + detail::stride() * row_); + } + + template + Component & entity_accessor::get() + { + if (auto ptr = get_if()) + return *ptr; + throw component_not_found_exception(typeid(Component), table_->entity_handles()[row_]); + } + + template + bool entity_accessor::contains() const + { + return get_if() != nullptr; + } + + inline entity_accessor::entity_accessor(detail::table * table, std::uint32_t row) + : table_(table) + , row_(row) + {} + +} diff --git a/libs/ecs/include/psemek/ecs/entity_container.hpp b/libs/ecs/include/psemek/ecs/entity_container.hpp index cb703d38..8b04a3f9 100644 --- a/libs/ecs/include/psemek/ecs/entity_container.hpp +++ b/libs/ecs/include/psemek/ecs/entity_container.hpp @@ -6,6 +6,7 @@ #include #include #include +#include #include #include #include @@ -19,66 +20,6 @@ namespace psemek::ecs using query_cache = std::shared_ptr; - struct component_not_found_exception - : util::exception - { - component_not_found_exception(std::type_info const & type, entity_handle const & handle, boost::stacktrace::stacktrace stacktrace = {}) - : util::exception(util::to_string("Component ", util::type_name(type), " not found for entity ", handle), std::move(stacktrace)) - , type_(type) - , handle_(handle) - {} - - std::type_info const & type() const - { - return type_; - } - - entity_handle const & handle() const - { - return handle_; - } - - private: - std::type_info const & type_; - entity_handle handle_; - }; - - struct entity_accessor - { - entity_accessor() = default; - entity_accessor(entity_accessor const &) = default; - - explicit operator bool() const; - - /** Obtain a pointer to the specified component type - * of the accessed entity, or a null pointer if - * the entity doesn't contain this component type. - */ - template - Component * get_if(); - - /** Obtain a reference to the specified component type - * of the accessed entity. - * If the entity doesn't contain this component type, - * an exception of type `component_not_found_exception` is thrown. - */ - template - Component & get(); - - /** Check if the entity contains this component type. - */ - template - bool contains() const; - - private: - detail::table * table_ = nullptr; - std::uint32_t row_ = 0; - - friend struct entity_container; - - entity_accessor(detail::table * table, std::uint32_t row); - }; - struct entity_container { /** Create an entity with the specified components. @@ -390,40 +331,4 @@ namespace psemek::ecs } } - inline entity_accessor::operator bool() const - { - return table_ != nullptr; - } - - template - Component * entity_accessor::get_if() - { - util::uuid const uuid = Component::uuid(); - - auto column = table_->column(uuid); - if (!column) - return nullptr; - - return reinterpret_cast(column->data() + detail::stride() * row_); - } - - template - Component & entity_accessor::get() - { - if (auto ptr = get_if()) - return *ptr; - throw component_not_found_exception(typeid(Component), table_->entity_handles()[row_]); - } - - template - bool entity_accessor::contains() const - { - return get_if() != nullptr; - } - - inline entity_accessor::entity_accessor(detail::table * table, std::uint32_t row) - : table_(table) - , row_(row) - {} - }